< prev index next >

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

Print this page

  91 
  92     // Lock held when writing
  93     private final ReentrantLock writeLock = new ReentrantLock();
  94 
  95     // The stateLock for read/changing state
  96     private final Object stateLock = new Object();
  97     private static final int ST_NEW = 0;
  98     private static final int ST_UNCONNECTED = 1;
  99     private static final int ST_CONNECTING = 2;
 100     private static final int ST_CONNECTED = 3;
 101     private static final int ST_CLOSING = 4;
 102     private static final int ST_CLOSED = 5;
 103     private volatile int state;  // need stateLock to change
 104 
 105     private Cleanable cleaner;
 106 
 107     // set to true when the socket is in non-blocking mode
 108     private volatile boolean nonBlocking;
 109 
 110     // used by connect/read/write/accept, protected by stateLock
 111     private long readerThread;
 112     private long writerThread;
 113 
 114     // used when SO_REUSEADDR is emulated, protected by stateLock
 115     private boolean isReuseAddress;
 116 
 117     // read or accept timeout in millis
 118     private volatile int timeout;
 119 
 120     // flags to indicate if the connection is shutdown for input and output
 121     private volatile boolean isInputClosed;
 122     private volatile boolean isOutputClosed;
 123 
 124     // used by read to emulate legacy behavior, protected by readLock
 125     private boolean readEOF;
 126     private boolean connectionReset;
 127 
 128     /**
 129      * Creates an instance of this SocketImpl.
 130      * @param server true if this is a SocketImpl for a ServerSocket
 131      */
 132     public NioSocketImpl(boolean server) {

 217     }
 218 
 219     /**
 220      * Marks the beginning of a read operation that might block.
 221      * @throws SocketException if the socket is closed or not connected
 222      */
 223     private FileDescriptor beginRead() throws SocketException {
 224         synchronized (stateLock) {
 225             ensureOpenAndConnected();
 226             readerThread = NativeThread.current();
 227             return fd;
 228         }
 229     }
 230 
 231     /**
 232      * Marks the end of a read operation that may have blocked.
 233      * @throws SocketException is the socket is closed
 234      */
 235     private void endRead(boolean completed) throws SocketException {
 236         synchronized (stateLock) {
 237             readerThread = 0;
 238             int state = this.state;
 239             if (state == ST_CLOSING)
 240                 tryFinishClose();
 241             if (!completed && state >= ST_CLOSING)
 242                 throw new SocketException("Socket closed");
 243         }
 244     }
 245 
 246     /**
 247      * Attempts to read bytes from the socket into the given byte array.
 248      */
 249     private int tryRead(FileDescriptor fd, byte[] b, int off, int len)
 250         throws IOException
 251     {
 252         ByteBuffer dst = Util.getTemporaryDirectBuffer(len);
 253         assert dst.position() == 0;
 254         try {
 255             int n = nd.read(fd, ((DirectBuffer)dst).address(), len);
 256             if (n > 0) {
 257                 dst.get(b, off, n);

 362     }
 363 
 364     /**
 365      * Marks the beginning of a write operation that might block.
 366      * @throws SocketException if the socket is closed or not connected
 367      */
 368     private FileDescriptor beginWrite() throws SocketException {
 369         synchronized (stateLock) {
 370             ensureOpenAndConnected();
 371             writerThread = NativeThread.current();
 372             return fd;
 373         }
 374     }
 375 
 376     /**
 377      * Marks the end of a write operation that may have blocked.
 378      * @throws SocketException is the socket is closed
 379      */
 380     private void endWrite(boolean completed) throws SocketException {
 381         synchronized (stateLock) {
 382             writerThread = 0;
 383             int state = this.state;
 384             if (state == ST_CLOSING)
 385                 tryFinishClose();
 386             if (!completed && state >= ST_CLOSING)
 387                 throw new SocketException("Socket closed");
 388         }
 389     }
 390 
 391     /**
 392      * Attempts to write a sequence of bytes to the socket from the given
 393      * byte array.
 394      */
 395     private int tryWrite(FileDescriptor fd, byte[] b, int off, int len)
 396         throws IOException
 397     {
 398         ByteBuffer src = Util.getTemporaryDirectBuffer(len);
 399         assert src.position() == 0;
 400         try {
 401             src.put(b, off, len);
 402             return nd.write(fd, ((DirectBuffer)src).address(), len);

 504             // invoke beforeTcpConnect hook if not already bound
 505             if (localport == 0) {
 506                 NetHooks.beforeTcpConnect(fd, address, port);
 507             }
 508 
 509             // save the remote address/port
 510             this.address = address;
 511             this.port = port;
 512 
 513             readerThread = NativeThread.current();
 514             return fd;
 515         }
 516     }
 517 
 518     /**
 519      * Marks the end of a connect operation that may have blocked.
 520      * @throws SocketException is the socket is closed
 521      */
 522     private void endConnect(FileDescriptor fd, boolean completed) throws IOException {
 523         synchronized (stateLock) {
 524             readerThread = 0;
 525             int state = this.state;
 526             if (state == ST_CLOSING)
 527                 tryFinishClose();
 528             if (completed && state == ST_CONNECTING) {
 529                 this.state = ST_CONNECTED;
 530                 localport = Net.localAddress(fd).getPort();
 531             } else if (!completed && state >= ST_CLOSING) {
 532                 throw new SocketException("Socket closed");
 533             }
 534         }
 535     }
 536 
 537     /**
 538      * Waits for a connection attempt to finish with a timeout
 539      * @throws SocketTimeoutException if the connect timeout elapses
 540      */
 541     private boolean timedFinishConnect(FileDescriptor fd, long nanos) throws IOException {
 542         long startNanos = System.nanoTime();
 543         boolean polled = Net.pollConnectNow(fd);
 544         while (!polled && isOpen()) {

 661      * Marks the beginning of an accept operation that might block.
 662      * @throws SocketException if the socket is closed
 663      */
 664     private FileDescriptor beginAccept() throws SocketException {
 665         synchronized (stateLock) {
 666             ensureOpen();
 667             if (localport == 0)
 668                 throw new SocketException("Not bound");
 669             readerThread = NativeThread.current();
 670             return fd;
 671         }
 672     }
 673 
 674     /**
 675      * Marks the end of an accept operation that may have blocked.
 676      * @throws SocketException is the socket is closed
 677      */
 678     private void endAccept(boolean completed) throws SocketException {
 679         synchronized (stateLock) {
 680             int state = this.state;
 681             readerThread = 0;
 682             if (state == ST_CLOSING)
 683                 tryFinishClose();
 684             if (!completed && state >= ST_CLOSING)
 685                 throw new SocketException("Socket closed");
 686         }
 687     }
 688 
 689     /**
 690      * Accepts a new connection with a timeout.
 691      * @throws SocketTimeoutException if the accept timeout elapses
 692      */
 693     private int timedAccept(FileDescriptor fd,
 694                             FileDescriptor newfd,
 695                             InetSocketAddress[] isaa,
 696                             long nanos)
 697         throws IOException
 698     {
 699         long startNanos = System.nanoTime();
 700         int n = Net.accept(fd, newfd, isaa);
 701         while (n == IOStatus.UNAVAILABLE && isOpen()) {

 827         };
 828     }
 829 
 830     @Override
 831     protected int available() throws IOException {
 832         synchronized (stateLock) {
 833             ensureOpenAndConnected();
 834             if (isInputClosed) {
 835                 return 0;
 836             } else {
 837                 return Net.available(fd);
 838             }
 839         }
 840     }
 841 
 842     /**
 843      * Closes the socket if there are no I/O operations in progress.
 844      */
 845     private boolean tryClose() throws IOException {
 846         assert Thread.holdsLock(stateLock) && state == ST_CLOSING;
 847         if (readerThread == 0 && writerThread == 0) {
 848             try {
 849                 cleaner.clean();
 850             } catch (UncheckedIOException ioe) {
 851                 throw ioe.getCause();
 852             } finally {
 853                 state = ST_CLOSED;
 854             }
 855             return true;
 856         } else {
 857             return false;
 858         }
 859     }
 860 
 861     /**
 862      * Invokes tryClose to attempt to close the socket.
 863      *
 864      * This method is used for deferred closing by I/O operations.
 865      */
 866     private void tryFinishClose() {
 867         try {

1127                         throw new SocketException("SO_REUSEPORT not supported");
1128                     return Net.getSocketOption(fd, StandardSocketOptions.SO_REUSEPORT);
1129                 default:
1130                     throw new SocketException("Unknown option " + opt);
1131                 }
1132             } catch (SocketException e) {
1133                 throw e;
1134             } catch (IllegalArgumentException | IOException e) {
1135                 throw asSocketException(e);
1136             }
1137         }
1138     }
1139 
1140     @Override
1141     protected void shutdownInput() throws IOException {
1142         synchronized (stateLock) {
1143             ensureOpenAndConnected();
1144             if (!isInputClosed) {
1145                 Net.shutdown(fd, Net.SHUT_RD);
1146                 if (NativeThread.isVirtualThread(readerThread)) {
1147                     Poller.stopPoll(fdVal(fd), Net.POLLIN);
1148                 }
1149                 isInputClosed = true;
1150             }
1151         }
1152     }
1153 
1154     @Override
1155     protected void shutdownOutput() throws IOException {
1156         synchronized (stateLock) {
1157             ensureOpenAndConnected();
1158             if (!isOutputClosed) {
1159                 Net.shutdown(fd, Net.SHUT_WR);
1160                 if (NativeThread.isVirtualThread(writerThread)) {
1161                     Poller.stopPoll(fdVal(fd), Net.POLLOUT);
1162                 }
1163                 isOutputClosed = true;
1164             }
1165         }
1166     }
1167 
1168     @Override
1169     protected boolean supportsUrgentData() {
1170         return true;
1171     }
1172 
1173     @Override
1174     protected void sendUrgentData(int data) throws IOException {
1175         writeLock.lock();
1176         try {
1177             int n = 0;
1178             FileDescriptor fd = beginWrite();
1179             try {
1180                 configureNonBlockingIfNeeded(fd, false);
1181                 do {

  91 
  92     // Lock held when writing
  93     private final ReentrantLock writeLock = new ReentrantLock();
  94 
  95     // The stateLock for read/changing state
  96     private final Object stateLock = new Object();
  97     private static final int ST_NEW = 0;
  98     private static final int ST_UNCONNECTED = 1;
  99     private static final int ST_CONNECTING = 2;
 100     private static final int ST_CONNECTED = 3;
 101     private static final int ST_CLOSING = 4;
 102     private static final int ST_CLOSED = 5;
 103     private volatile int state;  // need stateLock to change
 104 
 105     private Cleanable cleaner;
 106 
 107     // set to true when the socket is in non-blocking mode
 108     private volatile boolean nonBlocking;
 109 
 110     // used by connect/read/write/accept, protected by stateLock
 111     private NativeThread readerThread;
 112     private NativeThread writerThread;
 113 
 114     // used when SO_REUSEADDR is emulated, protected by stateLock
 115     private boolean isReuseAddress;
 116 
 117     // read or accept timeout in millis
 118     private volatile int timeout;
 119 
 120     // flags to indicate if the connection is shutdown for input and output
 121     private volatile boolean isInputClosed;
 122     private volatile boolean isOutputClosed;
 123 
 124     // used by read to emulate legacy behavior, protected by readLock
 125     private boolean readEOF;
 126     private boolean connectionReset;
 127 
 128     /**
 129      * Creates an instance of this SocketImpl.
 130      * @param server true if this is a SocketImpl for a ServerSocket
 131      */
 132     public NioSocketImpl(boolean server) {

 217     }
 218 
 219     /**
 220      * Marks the beginning of a read operation that might block.
 221      * @throws SocketException if the socket is closed or not connected
 222      */
 223     private FileDescriptor beginRead() throws SocketException {
 224         synchronized (stateLock) {
 225             ensureOpenAndConnected();
 226             readerThread = NativeThread.current();
 227             return fd;
 228         }
 229     }
 230 
 231     /**
 232      * Marks the end of a read operation that may have blocked.
 233      * @throws SocketException is the socket is closed
 234      */
 235     private void endRead(boolean completed) throws SocketException {
 236         synchronized (stateLock) {
 237             readerThread = null;
 238             int state = this.state;
 239             if (state == ST_CLOSING)
 240                 tryFinishClose();
 241             if (!completed && state >= ST_CLOSING)
 242                 throw new SocketException("Socket closed");
 243         }
 244     }
 245 
 246     /**
 247      * Attempts to read bytes from the socket into the given byte array.
 248      */
 249     private int tryRead(FileDescriptor fd, byte[] b, int off, int len)
 250         throws IOException
 251     {
 252         ByteBuffer dst = Util.getTemporaryDirectBuffer(len);
 253         assert dst.position() == 0;
 254         try {
 255             int n = nd.read(fd, ((DirectBuffer)dst).address(), len);
 256             if (n > 0) {
 257                 dst.get(b, off, n);

 362     }
 363 
 364     /**
 365      * Marks the beginning of a write operation that might block.
 366      * @throws SocketException if the socket is closed or not connected
 367      */
 368     private FileDescriptor beginWrite() throws SocketException {
 369         synchronized (stateLock) {
 370             ensureOpenAndConnected();
 371             writerThread = NativeThread.current();
 372             return fd;
 373         }
 374     }
 375 
 376     /**
 377      * Marks the end of a write operation that may have blocked.
 378      * @throws SocketException is the socket is closed
 379      */
 380     private void endWrite(boolean completed) throws SocketException {
 381         synchronized (stateLock) {
 382             writerThread = null;
 383             int state = this.state;
 384             if (state == ST_CLOSING)
 385                 tryFinishClose();
 386             if (!completed && state >= ST_CLOSING)
 387                 throw new SocketException("Socket closed");
 388         }
 389     }
 390 
 391     /**
 392      * Attempts to write a sequence of bytes to the socket from the given
 393      * byte array.
 394      */
 395     private int tryWrite(FileDescriptor fd, byte[] b, int off, int len)
 396         throws IOException
 397     {
 398         ByteBuffer src = Util.getTemporaryDirectBuffer(len);
 399         assert src.position() == 0;
 400         try {
 401             src.put(b, off, len);
 402             return nd.write(fd, ((DirectBuffer)src).address(), len);

 504             // invoke beforeTcpConnect hook if not already bound
 505             if (localport == 0) {
 506                 NetHooks.beforeTcpConnect(fd, address, port);
 507             }
 508 
 509             // save the remote address/port
 510             this.address = address;
 511             this.port = port;
 512 
 513             readerThread = NativeThread.current();
 514             return fd;
 515         }
 516     }
 517 
 518     /**
 519      * Marks the end of a connect operation that may have blocked.
 520      * @throws SocketException is the socket is closed
 521      */
 522     private void endConnect(FileDescriptor fd, boolean completed) throws IOException {
 523         synchronized (stateLock) {
 524             readerThread = null;
 525             int state = this.state;
 526             if (state == ST_CLOSING)
 527                 tryFinishClose();
 528             if (completed && state == ST_CONNECTING) {
 529                 this.state = ST_CONNECTED;
 530                 localport = Net.localAddress(fd).getPort();
 531             } else if (!completed && state >= ST_CLOSING) {
 532                 throw new SocketException("Socket closed");
 533             }
 534         }
 535     }
 536 
 537     /**
 538      * Waits for a connection attempt to finish with a timeout
 539      * @throws SocketTimeoutException if the connect timeout elapses
 540      */
 541     private boolean timedFinishConnect(FileDescriptor fd, long nanos) throws IOException {
 542         long startNanos = System.nanoTime();
 543         boolean polled = Net.pollConnectNow(fd);
 544         while (!polled && isOpen()) {

 661      * Marks the beginning of an accept operation that might block.
 662      * @throws SocketException if the socket is closed
 663      */
 664     private FileDescriptor beginAccept() throws SocketException {
 665         synchronized (stateLock) {
 666             ensureOpen();
 667             if (localport == 0)
 668                 throw new SocketException("Not bound");
 669             readerThread = NativeThread.current();
 670             return fd;
 671         }
 672     }
 673 
 674     /**
 675      * Marks the end of an accept operation that may have blocked.
 676      * @throws SocketException is the socket is closed
 677      */
 678     private void endAccept(boolean completed) throws SocketException {
 679         synchronized (stateLock) {
 680             int state = this.state;
 681             readerThread = null;
 682             if (state == ST_CLOSING)
 683                 tryFinishClose();
 684             if (!completed && state >= ST_CLOSING)
 685                 throw new SocketException("Socket closed");
 686         }
 687     }
 688 
 689     /**
 690      * Accepts a new connection with a timeout.
 691      * @throws SocketTimeoutException if the accept timeout elapses
 692      */
 693     private int timedAccept(FileDescriptor fd,
 694                             FileDescriptor newfd,
 695                             InetSocketAddress[] isaa,
 696                             long nanos)
 697         throws IOException
 698     {
 699         long startNanos = System.nanoTime();
 700         int n = Net.accept(fd, newfd, isaa);
 701         while (n == IOStatus.UNAVAILABLE && isOpen()) {

 827         };
 828     }
 829 
 830     @Override
 831     protected int available() throws IOException {
 832         synchronized (stateLock) {
 833             ensureOpenAndConnected();
 834             if (isInputClosed) {
 835                 return 0;
 836             } else {
 837                 return Net.available(fd);
 838             }
 839         }
 840     }
 841 
 842     /**
 843      * Closes the socket if there are no I/O operations in progress.
 844      */
 845     private boolean tryClose() throws IOException {
 846         assert Thread.holdsLock(stateLock) && state == ST_CLOSING;
 847         if (readerThread == null && writerThread == null) {
 848             try {
 849                 cleaner.clean();
 850             } catch (UncheckedIOException ioe) {
 851                 throw ioe.getCause();
 852             } finally {
 853                 state = ST_CLOSED;
 854             }
 855             return true;
 856         } else {
 857             return false;
 858         }
 859     }
 860 
 861     /**
 862      * Invokes tryClose to attempt to close the socket.
 863      *
 864      * This method is used for deferred closing by I/O operations.
 865      */
 866     private void tryFinishClose() {
 867         try {

1127                         throw new SocketException("SO_REUSEPORT not supported");
1128                     return Net.getSocketOption(fd, StandardSocketOptions.SO_REUSEPORT);
1129                 default:
1130                     throw new SocketException("Unknown option " + opt);
1131                 }
1132             } catch (SocketException e) {
1133                 throw e;
1134             } catch (IllegalArgumentException | IOException e) {
1135                 throw asSocketException(e);
1136             }
1137         }
1138     }
1139 
1140     @Override
1141     protected void shutdownInput() throws IOException {
1142         synchronized (stateLock) {
1143             ensureOpenAndConnected();
1144             if (!isInputClosed) {
1145                 Net.shutdown(fd, Net.SHUT_RD);
1146                 if (NativeThread.isVirtualThread(readerThread)) {
1147                     Poller.stopPoll(readerThread.thread());
1148                 }
1149                 isInputClosed = true;
1150             }
1151         }
1152     }
1153 
1154     @Override
1155     protected void shutdownOutput() throws IOException {
1156         synchronized (stateLock) {
1157             ensureOpenAndConnected();
1158             if (!isOutputClosed) {
1159                 Net.shutdown(fd, Net.SHUT_WR);
1160                 if (NativeThread.isVirtualThread(writerThread)) {
1161                     Poller.stopPoll(writerThread.thread());
1162                 }
1163                 isOutputClosed = true;
1164             }
1165         }
1166     }
1167 
1168     @Override
1169     protected boolean supportsUrgentData() {
1170         return true;
1171     }
1172 
1173     @Override
1174     protected void sendUrgentData(int data) throws IOException {
1175         writeLock.lock();
1176         try {
1177             int n = 0;
1178             FileDescriptor fd = beginWrite();
1179             try {
1180                 configureNonBlockingIfNeeded(fd, false);
1181                 do {
< prev index next >