< prev index next >

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

Print this page

 106 
 107     // State, increases monotonically
 108     private static final int ST_UNCONNECTED = 0;
 109     private static final int ST_CONNECTIONPENDING = 1;
 110     private static final int ST_CONNECTED = 2;
 111     private static final int ST_CLOSING = 3;
 112     private static final int ST_CLOSED = 4;
 113     private volatile int state;  // need stateLock to change
 114 
 115     // IDs of native threads doing reads and writes, for signalling
 116     private long readerThread;
 117     private long writerThread;
 118 
 119     // Binding
 120     private SocketAddress localAddress;
 121     private SocketAddress remoteAddress;
 122 
 123     // Socket adaptor, created on demand
 124     private Socket socket;
 125 



 126     // -- End of fields protected by stateLock
 127 
 128     SocketChannelImpl(SelectorProvider sp) throws IOException {
 129         this(sp, Net.isIPv6Available() ? INET6 : INET);
 130     }
 131 
 132     SocketChannelImpl(SelectorProvider sp, ProtocolFamily family) throws IOException {
 133         super(sp);
 134         Objects.requireNonNull(family, "'family' is null");
 135         if ((family != INET) && (family != INET6) && (family != UNIX)) {
 136             throw new UnsupportedOperationException("Protocol family not supported");
 137         }
 138         if (family == INET6 && !Net.isIPv6Available()) {
 139             throw new UnsupportedOperationException("IPv6 not available");
 140         }
 141 
 142         this.family = family;
 143         if (family == UNIX) {
 144             this.fd = UnixDomainSockets.socket();
 145         } else {

 397     @Override
 398     public int read(ByteBuffer buf) throws IOException {
 399         Objects.requireNonNull(buf);
 400 
 401         readLock.lock();
 402         try {
 403             ensureOpenAndConnected();
 404             boolean blocking = isBlocking();
 405             int n = 0;
 406             try {
 407                 beginRead(blocking);
 408 
 409                 // check if connection has been reset
 410                 if (connectionReset)
 411                     throwConnectionReset();
 412 
 413                 // check if input is shutdown
 414                 if (isInputClosed)
 415                     return IOStatus.EOF;
 416 

 417                 n = IOUtil.read(fd, buf, -1, nd);
 418                 if (blocking) {
 419                     while (IOStatus.okayToRetry(n) && isOpen()) {
 420                         park(Net.POLLIN);
 421                         n = IOUtil.read(fd, buf, -1, nd);
 422                     }
 423                 }
 424             } catch (ConnectionResetException e) {
 425                 connectionReset = true;
 426                 throwConnectionReset();
 427             } finally {
 428                 endRead(blocking, n > 0);
 429                 if (n <= 0 && isInputClosed)
 430                     return IOStatus.EOF;
 431             }
 432             return IOStatus.normalize(n);
 433         } finally {
 434             readLock.unlock();
 435         }
 436     }

 440         throws IOException
 441     {
 442         Objects.checkFromIndexSize(offset, length, dsts.length);
 443 
 444         readLock.lock();
 445         try {
 446             ensureOpenAndConnected();
 447             boolean blocking = isBlocking();
 448             long n = 0;
 449             try {
 450                 beginRead(blocking);
 451 
 452                 // check if connection has been reset
 453                 if (connectionReset)
 454                     throwConnectionReset();
 455 
 456                 // check if input is shutdown
 457                 if (isInputClosed)
 458                     return IOStatus.EOF;
 459 

 460                 n = IOUtil.read(fd, dsts, offset, length, nd);
 461                 if (blocking) {
 462                     while (IOStatus.okayToRetry(n) && isOpen()) {
 463                         park(Net.POLLIN);
 464                         n = IOUtil.read(fd, dsts, offset, length, nd);
 465                     }
 466                 }
 467             } catch (ConnectionResetException e) {
 468                 connectionReset = true;
 469                 throwConnectionReset();
 470             } finally {
 471                 endRead(blocking, n > 0);
 472                 if (n <= 0 && isInputClosed)
 473                     return IOStatus.EOF;
 474             }
 475             return IOStatus.normalize(n);
 476         } finally {
 477             readLock.unlock();
 478         }
 479     }

 512                 writerThread = 0;
 513                 if (state == ST_CLOSING) {
 514                     tryFinishClose();
 515                 }
 516             }
 517             // remove hook for Thread.interrupt
 518             end(completed);
 519         }
 520     }
 521 
 522     @Override
 523     public int write(ByteBuffer buf) throws IOException {
 524         Objects.requireNonNull(buf);
 525         writeLock.lock();
 526         try {
 527             ensureOpenAndConnected();
 528             boolean blocking = isBlocking();
 529             int n = 0;
 530             try {
 531                 beginWrite(blocking);

 532                 n = IOUtil.write(fd, buf, -1, nd);
 533                 if (blocking) {
 534                     while (IOStatus.okayToRetry(n) && isOpen()) {
 535                         park(Net.POLLOUT);
 536                         n = IOUtil.write(fd, buf, -1, nd);
 537                     }
 538                 }
 539             } finally {
 540                 endWrite(blocking, n > 0);
 541                 if (n <= 0 && isOutputClosed)
 542                     throw new AsynchronousCloseException();
 543             }
 544             return IOStatus.normalize(n);
 545         } finally {
 546             writeLock.unlock();
 547         }
 548     }
 549 
 550     @Override
 551     public long write(ByteBuffer[] srcs, int offset, int length)
 552         throws IOException
 553     {
 554         Objects.checkFromIndexSize(offset, length, srcs.length);
 555 
 556         writeLock.lock();
 557         try {
 558             ensureOpenAndConnected();
 559             boolean blocking = isBlocking();
 560             long n = 0;
 561             try {
 562                 beginWrite(blocking);

 563                 n = IOUtil.write(fd, srcs, offset, length, nd);
 564                 if (blocking) {
 565                     while (IOStatus.okayToRetry(n) && isOpen()) {
 566                         park(Net.POLLOUT);
 567                         n = IOUtil.write(fd, srcs, offset, length, nd);
 568                     }
 569                 }
 570             } finally {
 571                 endWrite(blocking, n > 0);
 572                 if (n <= 0 && isOutputClosed)
 573                     throw new AsynchronousCloseException();
 574             }
 575             return IOStatus.normalize(n);
 576         } finally {
 577             writeLock.unlock();
 578         }
 579     }
 580 
 581     /**
 582      * Writes a byte of out of band data.
 583      */
 584     int sendOutOfBandData(byte b) throws IOException {
 585         writeLock.lock();
 586         try {
 587             ensureOpenAndConnected();
 588             boolean blocking = isBlocking();
 589             int n = 0;
 590             try {
 591                 beginWrite(blocking);
 592                 if (blocking) {
 593                     do {
 594                         n = Net.sendOOB(fd, b);
 595                     } while (n == IOStatus.INTERRUPTED && isOpen());
 596                 } else {
 597                     n = Net.sendOOB(fd, b);



 598                 }
 599             } finally {
 600                 endWrite(blocking, n > 0);
 601                 if (n <= 0 && isOutputClosed)
 602                     throw new AsynchronousCloseException();
 603             }
 604             return IOStatus.normalize(n);
 605         } finally {
 606             writeLock.unlock();
 607         }
 608     }
 609 
 610     @Override
 611     protected void implConfigureBlocking(boolean block) throws IOException {
 612         readLock.lock();
 613         try {
 614             writeLock.lock();
 615             try {
 616                 lockedConfigureBlocking(block);
 617             } finally {
 618                 writeLock.unlock();
 619             }
 620         } finally {
 621             readLock.unlock();
 622         }
 623     }
 624 
 625     /**
 626      * Adjusts the blocking mode. readLock or writeLock must already be held.
 627      */
 628     private void lockedConfigureBlocking(boolean block) throws IOException {
 629         assert readLock.isHeldByCurrentThread() || writeLock.isHeldByCurrentThread();
 630         synchronized (stateLock) {
 631             ensureOpen();
 632             IOUtil.configureBlocking(fd, block);



 633         }
 634     }
 635 
 636     /**
 637      * Adjusts the blocking mode if the channel is open. readLock or writeLock
 638      * must already be held.
 639      *
 640      * @return {@code true} if the blocking mode was adjusted, {@code false} if
 641      *         the blocking mode was not adjusted because the channel is closed
 642      */
 643     private boolean tryLockedConfigureBlocking(boolean block) throws IOException {
 644         assert readLock.isHeldByCurrentThread() || writeLock.isHeldByCurrentThread();
 645         synchronized (stateLock) {
 646             if (isOpen()) {

 647                 IOUtil.configureBlocking(fd, block);
 648                 return true;
 649             } else {
 650                 return false;
 651             }
 652         }
 653     }
 654 















 655     /**
 656      * Returns the local address, or null if not bound
 657      */
 658     SocketAddress localAddress() {
 659         synchronized (stateLock) {
 660             return localAddress;
 661         }
 662     }
 663 
 664     /**
 665      * Returns the remote address, or null if not connected
 666      */
 667     SocketAddress remoteAddress() {
 668         synchronized (stateLock) {
 669             return remoteAddress;
 670         }
 671     }
 672 
 673     @Override
 674     public SocketChannel bind(SocketAddress local) throws IOException {

 829                     return new InetSocketAddress(Net.inet6LoopbackAddress(), port);
 830                 }
 831             } else {
 832                 return isa;
 833             }
 834         }
 835     }
 836 
 837     @Override
 838     public boolean connect(SocketAddress remote) throws IOException {
 839         SocketAddress sa = checkRemote(remote);
 840         try {
 841             readLock.lock();
 842             try {
 843                 writeLock.lock();
 844                 try {
 845                     boolean blocking = isBlocking();
 846                     boolean connected = false;
 847                     try {
 848                         beginConnect(blocking, sa);

 849                         int n;
 850                         if (isUnixSocket()) {
 851                             n = UnixDomainSockets.connect(fd, sa);
 852                         } else {
 853                             n = Net.connect(family, fd, sa);
 854                         }
 855                         if (n > 0) {
 856                             connected = true;
 857                         } else if (blocking) {
 858                             assert IOStatus.okayToRetry(n);
 859                             boolean polled = false;
 860                             while (!polled && isOpen()) {
 861                                 park(Net.POLLOUT);
 862                                 polled = Net.pollConnectNow(fd);
 863                             }
 864                             connected = polled && isOpen();
 865                         }
 866                     } finally {
 867                         endConnect(blocking, connected);
 868                     }

 992     private void tryFinishClose() {
 993         try {
 994             tryClose();
 995         } catch (IOException ignore) { }
 996     }
 997 
 998     /**
 999      * Closes this channel when configured in blocking mode.
1000      *
1001      * If there is an I/O operation in progress then the socket is pre-closed
1002      * and the I/O threads signalled, in which case the final close is deferred
1003      * until all I/O operations complete.
1004      *
1005      * Note that a channel configured blocking may be registered with a Selector
1006      * This arises when a key is canceled and the channel configured to blocking
1007      * mode before the key is flushed from the Selector.
1008      */
1009     private void implCloseBlockingMode() throws IOException {
1010         synchronized (stateLock) {
1011             assert state < ST_CLOSING;

1012             state = ST_CLOSING;

1013             if (!tryClose()) {










1014                 long reader = readerThread;
1015                 long writer = writerThread;
1016                 if (reader != 0 || writer != 0) {





1017                     nd.preClose(fd);
1018                     if (reader != 0)
1019                         NativeThread.signal(reader);
1020                     if (writer != 0)
1021                         NativeThread.signal(writer);
1022                 }
1023             }
1024         }
1025     }
1026 
1027     /**
1028      * Closes this channel when configured in non-blocking mode.
1029      *
1030      * If the channel is registered with a Selector then the close is deferred
1031      * until the channel is flushed from all Selectors.
1032      *
1033      * If the socket is connected and the channel is registered with a Selector
1034      * then the socket is shutdown for writing so that the peer reads EOF. In
1035      * addition, if SO_LINGER is set to a non-zero value then it is disabled so
1036      * that the deferred close does not wait.
1037      */
1038     private void implCloseNonBlockingMode() throws IOException {
1039         boolean connected;
1040         synchronized (stateLock) {

1081         }
1082     }
1083 
1084     @Override
1085     public void kill() {
1086         synchronized (stateLock) {
1087             if (state == ST_CLOSING) {
1088                 tryFinishClose();
1089             }
1090         }
1091     }
1092 
1093     @Override
1094     public SocketChannel shutdownInput() throws IOException {
1095         synchronized (stateLock) {
1096             ensureOpen();
1097             if (!isConnected())
1098                 throw new NotYetConnectedException();
1099             if (!isInputClosed) {
1100                 Net.shutdown(fd, Net.SHUT_RD);
1101                 long thread = readerThread;
1102                 if (thread != 0)
1103                     NativeThread.signal(thread);



1104                 isInputClosed = true;
1105             }
1106             return this;
1107         }
1108     }
1109 
1110     @Override
1111     public SocketChannel shutdownOutput() throws IOException {
1112         synchronized (stateLock) {
1113             ensureOpen();
1114             if (!isConnected())
1115                 throw new NotYetConnectedException();
1116             if (!isOutputClosed) {
1117                 Net.shutdown(fd, Net.SHUT_WR);
1118                 long thread = writerThread;
1119                 if (thread != 0)
1120                     NativeThread.signal(thread);



1121                 isOutputClosed = true;
1122             }
1123             return this;
1124         }
1125     }
1126 
1127     boolean isInputOpen() {
1128         return !isInputClosed;
1129     }
1130 
1131     boolean isOutputOpen() {
1132         return !isOutputClosed;
1133     }
1134 
1135     /**
1136      * Waits for a connection attempt to finish with a timeout
1137      * @throws SocketTimeoutException if the connect timeout elapses
1138      */
1139     private boolean finishTimedConnect(long nanos) throws IOException {
1140         long startNanos = System.nanoTime();

1265 
1266                 // check if connection has been reset
1267                 if (connectionReset)
1268                     throwConnectionReset();
1269 
1270                 // check if input is shutdown
1271                 if (isInputClosed)
1272                     return IOStatus.EOF;
1273 
1274                 if (nanos > 0) {
1275                     // change socket to non-blocking
1276                     lockedConfigureBlocking(false);
1277                     try {
1278                         n = timedRead(b, off, len, nanos);
1279                     } finally {
1280                         // restore socket to blocking mode (if channel is open)
1281                         tryLockedConfigureBlocking(true);
1282                     }
1283                 } else {
1284                     // read, no timeout

1285                     n = tryRead(b, off, len);
1286                     while (IOStatus.okayToRetry(n) && isOpen()) {
1287                         park(Net.POLLIN);
1288                         n = tryRead(b, off, len);
1289                     }
1290                 }
1291             } catch (ConnectionResetException e) {
1292                 connectionReset = true;
1293                 throwConnectionReset();
1294             } finally {
1295                 endRead(true, n > 0);
1296                 if (n <= 0 && isInputClosed)
1297                     return IOStatus.EOF;
1298             }
1299             assert n > 0 || n == -1;
1300             return n;
1301         } finally {
1302             readLock.unlock();
1303         }
1304     }

1326     void blockingWriteFully(byte[] b, int off, int len) throws IOException {
1327         Objects.checkFromIndexSize(off, len, b.length);
1328         if (len == 0) {
1329             // nothing to do
1330             return;
1331         }
1332 
1333         writeLock.lock();
1334         try {
1335             ensureOpenAndConnected();
1336 
1337             // check that channel is configured blocking
1338             if (!isBlocking())
1339                 throw new IllegalBlockingModeException();
1340 
1341             // loop until all bytes have been written
1342             int pos = off;
1343             int end = off + len;
1344             try {
1345                 beginWrite(true);

1346                 while (pos < end && isOpen()) {
1347                     int size = end - pos;
1348                     int n = tryWrite(b, pos, size);
1349                     while (IOStatus.okayToRetry(n) && isOpen()) {
1350                         park(Net.POLLOUT);
1351                         n = tryWrite(b, pos, size);
1352                     }
1353                     if (n > 0) {
1354                         pos += n;
1355                     }
1356                 }
1357             } finally {
1358                 endWrite(true, pos >= end);
1359             }
1360         } finally {
1361             writeLock.unlock();
1362         }
1363     }
1364 
1365     /**

 106 
 107     // State, increases monotonically
 108     private static final int ST_UNCONNECTED = 0;
 109     private static final int ST_CONNECTIONPENDING = 1;
 110     private static final int ST_CONNECTED = 2;
 111     private static final int ST_CLOSING = 3;
 112     private static final int ST_CLOSED = 4;
 113     private volatile int state;  // need stateLock to change
 114 
 115     // IDs of native threads doing reads and writes, for signalling
 116     private long readerThread;
 117     private long writerThread;
 118 
 119     // Binding
 120     private SocketAddress localAddress;
 121     private SocketAddress remoteAddress;
 122 
 123     // Socket adaptor, created on demand
 124     private Socket socket;
 125 
 126     // lazily set to true when the socket is configured non-blocking
 127     private volatile boolean nonBlocking;
 128 
 129     // -- End of fields protected by stateLock
 130 
 131     SocketChannelImpl(SelectorProvider sp) throws IOException {
 132         this(sp, Net.isIPv6Available() ? INET6 : INET);
 133     }
 134 
 135     SocketChannelImpl(SelectorProvider sp, ProtocolFamily family) throws IOException {
 136         super(sp);
 137         Objects.requireNonNull(family, "'family' is null");
 138         if ((family != INET) && (family != INET6) && (family != UNIX)) {
 139             throw new UnsupportedOperationException("Protocol family not supported");
 140         }
 141         if (family == INET6 && !Net.isIPv6Available()) {
 142             throw new UnsupportedOperationException("IPv6 not available");
 143         }
 144 
 145         this.family = family;
 146         if (family == UNIX) {
 147             this.fd = UnixDomainSockets.socket();
 148         } else {

 400     @Override
 401     public int read(ByteBuffer buf) throws IOException {
 402         Objects.requireNonNull(buf);
 403 
 404         readLock.lock();
 405         try {
 406             ensureOpenAndConnected();
 407             boolean blocking = isBlocking();
 408             int n = 0;
 409             try {
 410                 beginRead(blocking);
 411 
 412                 // check if connection has been reset
 413                 if (connectionReset)
 414                     throwConnectionReset();
 415 
 416                 // check if input is shutdown
 417                 if (isInputClosed)
 418                     return IOStatus.EOF;
 419 
 420                 configureNonBlockingIfNeeded();
 421                 n = IOUtil.read(fd, buf, -1, nd);
 422                 if (blocking) {
 423                     while (IOStatus.okayToRetry(n) && isOpen()) {
 424                         park(Net.POLLIN);
 425                         n = IOUtil.read(fd, buf, -1, nd);
 426                     }
 427                 }
 428             } catch (ConnectionResetException e) {
 429                 connectionReset = true;
 430                 throwConnectionReset();
 431             } finally {
 432                 endRead(blocking, n > 0);
 433                 if (n <= 0 && isInputClosed)
 434                     return IOStatus.EOF;
 435             }
 436             return IOStatus.normalize(n);
 437         } finally {
 438             readLock.unlock();
 439         }
 440     }

 444         throws IOException
 445     {
 446         Objects.checkFromIndexSize(offset, length, dsts.length);
 447 
 448         readLock.lock();
 449         try {
 450             ensureOpenAndConnected();
 451             boolean blocking = isBlocking();
 452             long n = 0;
 453             try {
 454                 beginRead(blocking);
 455 
 456                 // check if connection has been reset
 457                 if (connectionReset)
 458                     throwConnectionReset();
 459 
 460                 // check if input is shutdown
 461                 if (isInputClosed)
 462                     return IOStatus.EOF;
 463 
 464                 configureNonBlockingIfNeeded();
 465                 n = IOUtil.read(fd, dsts, offset, length, nd);
 466                 if (blocking) {
 467                     while (IOStatus.okayToRetry(n) && isOpen()) {
 468                         park(Net.POLLIN);
 469                         n = IOUtil.read(fd, dsts, offset, length, nd);
 470                     }
 471                 }
 472             } catch (ConnectionResetException e) {
 473                 connectionReset = true;
 474                 throwConnectionReset();
 475             } finally {
 476                 endRead(blocking, n > 0);
 477                 if (n <= 0 && isInputClosed)
 478                     return IOStatus.EOF;
 479             }
 480             return IOStatus.normalize(n);
 481         } finally {
 482             readLock.unlock();
 483         }
 484     }

 517                 writerThread = 0;
 518                 if (state == ST_CLOSING) {
 519                     tryFinishClose();
 520                 }
 521             }
 522             // remove hook for Thread.interrupt
 523             end(completed);
 524         }
 525     }
 526 
 527     @Override
 528     public int write(ByteBuffer buf) throws IOException {
 529         Objects.requireNonNull(buf);
 530         writeLock.lock();
 531         try {
 532             ensureOpenAndConnected();
 533             boolean blocking = isBlocking();
 534             int n = 0;
 535             try {
 536                 beginWrite(blocking);
 537                 configureNonBlockingIfNeeded();
 538                 n = IOUtil.write(fd, buf, -1, nd);
 539                 if (blocking) {
 540                     while (IOStatus.okayToRetry(n) && isOpen()) {
 541                         park(Net.POLLOUT);
 542                         n = IOUtil.write(fd, buf, -1, nd);
 543                     }
 544                 }
 545             } finally {
 546                 endWrite(blocking, n > 0);
 547                 if (n <= 0 && isOutputClosed)
 548                     throw new AsynchronousCloseException();
 549             }
 550             return IOStatus.normalize(n);
 551         } finally {
 552             writeLock.unlock();
 553         }
 554     }
 555 
 556     @Override
 557     public long write(ByteBuffer[] srcs, int offset, int length)
 558         throws IOException
 559     {
 560         Objects.checkFromIndexSize(offset, length, srcs.length);
 561 
 562         writeLock.lock();
 563         try {
 564             ensureOpenAndConnected();
 565             boolean blocking = isBlocking();
 566             long n = 0;
 567             try {
 568                 beginWrite(blocking);
 569                 configureNonBlockingIfNeeded();
 570                 n = IOUtil.write(fd, srcs, offset, length, nd);
 571                 if (blocking) {
 572                     while (IOStatus.okayToRetry(n) && isOpen()) {
 573                         park(Net.POLLOUT);
 574                         n = IOUtil.write(fd, srcs, offset, length, nd);
 575                     }
 576                 }
 577             } finally {
 578                 endWrite(blocking, n > 0);
 579                 if (n <= 0 && isOutputClosed)
 580                     throw new AsynchronousCloseException();
 581             }
 582             return IOStatus.normalize(n);
 583         } finally {
 584             writeLock.unlock();
 585         }
 586     }
 587 
 588     /**
 589      * Writes a byte of out of band data.
 590      */
 591     int sendOutOfBandData(byte b) throws IOException {
 592         writeLock.lock();
 593         try {
 594             ensureOpenAndConnected();
 595             boolean blocking = isBlocking();
 596             int n = 0;
 597             try {
 598                 beginWrite(blocking);
 599                 configureNonBlockingIfNeeded();
 600                 do {



 601                     n = Net.sendOOB(fd, b);
 602                 } while (n == IOStatus.INTERRUPTED && isOpen());
 603                 if (blocking && n == IOStatus.UNAVAILABLE) {
 604                     throw new SocketException("No buffer space available");
 605                 }
 606             } finally {
 607                 endWrite(blocking, n > 0);
 608                 if (n <= 0 && isOutputClosed)
 609                     throw new AsynchronousCloseException();
 610             }
 611             return IOStatus.normalize(n);
 612         } finally {
 613             writeLock.unlock();
 614         }
 615     }
 616 
 617     @Override
 618     protected void implConfigureBlocking(boolean block) throws IOException {
 619         readLock.lock();
 620         try {
 621             writeLock.lock();
 622             try {
 623                 lockedConfigureBlocking(block);
 624             } finally {
 625                 writeLock.unlock();
 626             }
 627         } finally {
 628             readLock.unlock();
 629         }
 630     }
 631 
 632     /**
 633      * Adjust the blocking mode while holding readLock or writeLock.
 634      */
 635     private void lockedConfigureBlocking(boolean block) throws IOException {
 636         assert readLock.isHeldByCurrentThread() || writeLock.isHeldByCurrentThread();
 637         synchronized (stateLock) {
 638             ensureOpen();
 639             // do nothing if virtual thread has forced the socket to be non-blocking
 640             if (!nonBlocking) {
 641                 IOUtil.configureBlocking(fd, block);
 642             }
 643         }
 644     }
 645 
 646     /**
 647      * Attempts to adjusts the blocking mode if the channel is open.
 648      * @return {@code true} if the blocking mode was adjusted



 649      */
 650     private boolean tryLockedConfigureBlocking(boolean block) throws IOException {
 651         assert readLock.isHeldByCurrentThread() || writeLock.isHeldByCurrentThread();
 652         synchronized (stateLock) {
 653             // do nothing if virtual thread has forced the socket to be non-blocking
 654             if (!nonBlocking && isOpen()) {
 655                 IOUtil.configureBlocking(fd, block);
 656                 return true;
 657             } else {
 658                 return false;
 659             }
 660         }
 661     }
 662 
 663     /**
 664      * Ensures that the socket is configured non-blocking when on a virtual
 665      * thread.
 666      */
 667     private void configureNonBlockingIfNeeded() throws IOException {
 668         assert readLock.isHeldByCurrentThread() || writeLock.isHeldByCurrentThread();
 669         if (!nonBlocking && Thread.currentThread().isVirtual()) {
 670             synchronized (stateLock) {
 671                 ensureOpen();
 672                 IOUtil.configureBlocking(fd, false);
 673                 nonBlocking = true;
 674             }
 675         }
 676     }
 677 
 678     /**
 679      * Returns the local address, or null if not bound
 680      */
 681     SocketAddress localAddress() {
 682         synchronized (stateLock) {
 683             return localAddress;
 684         }
 685     }
 686 
 687     /**
 688      * Returns the remote address, or null if not connected
 689      */
 690     SocketAddress remoteAddress() {
 691         synchronized (stateLock) {
 692             return remoteAddress;
 693         }
 694     }
 695 
 696     @Override
 697     public SocketChannel bind(SocketAddress local) throws IOException {

 852                     return new InetSocketAddress(Net.inet6LoopbackAddress(), port);
 853                 }
 854             } else {
 855                 return isa;
 856             }
 857         }
 858     }
 859 
 860     @Override
 861     public boolean connect(SocketAddress remote) throws IOException {
 862         SocketAddress sa = checkRemote(remote);
 863         try {
 864             readLock.lock();
 865             try {
 866                 writeLock.lock();
 867                 try {
 868                     boolean blocking = isBlocking();
 869                     boolean connected = false;
 870                     try {
 871                         beginConnect(blocking, sa);
 872                         configureNonBlockingIfNeeded();
 873                         int n;
 874                         if (isUnixSocket()) {
 875                             n = UnixDomainSockets.connect(fd, sa);
 876                         } else {
 877                             n = Net.connect(family, fd, sa);
 878                         }
 879                         if (n > 0) {
 880                             connected = true;
 881                         } else if (blocking) {
 882                             assert IOStatus.okayToRetry(n);
 883                             boolean polled = false;
 884                             while (!polled && isOpen()) {
 885                                 park(Net.POLLOUT);
 886                                 polled = Net.pollConnectNow(fd);
 887                             }
 888                             connected = polled && isOpen();
 889                         }
 890                     } finally {
 891                         endConnect(blocking, connected);
 892                     }

1016     private void tryFinishClose() {
1017         try {
1018             tryClose();
1019         } catch (IOException ignore) { }
1020     }
1021 
1022     /**
1023      * Closes this channel when configured in blocking mode.
1024      *
1025      * If there is an I/O operation in progress then the socket is pre-closed
1026      * and the I/O threads signalled, in which case the final close is deferred
1027      * until all I/O operations complete.
1028      *
1029      * Note that a channel configured blocking may be registered with a Selector
1030      * This arises when a key is canceled and the channel configured to blocking
1031      * mode before the key is flushed from the Selector.
1032      */
1033     private void implCloseBlockingMode() throws IOException {
1034         synchronized (stateLock) {
1035             assert state < ST_CLOSING;
1036             boolean connected = (state == ST_CONNECTED);
1037             state = ST_CLOSING;
1038 
1039             if (!tryClose()) {
1040                 // shutdown output when linger interval not set to 0
1041                 if (connected) {
1042                     try {
1043                         var SO_LINGER = StandardSocketOptions.SO_LINGER;
1044                         if ((int) Net.getSocketOption(fd, SO_LINGER) != 0) {
1045                             Net.shutdown(fd, Net.SHUT_WR);
1046                         }
1047                     } catch (IOException ignore) { }
1048                 }
1049 
1050                 long reader = readerThread;
1051                 long writer = writerThread;
1052                 if (NativeThread.isVirtualThread(reader)
1053                         || NativeThread.isVirtualThread(writer)) {
1054                     Poller.stopPoll(fdVal);
1055                 }
1056                 if (NativeThread.isKernelThread(reader)
1057                         || NativeThread.isKernelThread(writer)) {
1058                     nd.preClose(fd);
1059                     if (NativeThread.isKernelThread(reader))
1060                         NativeThread.signal(reader);
1061                     if (NativeThread.isKernelThread(writer))
1062                         NativeThread.signal(writer);
1063                 }
1064             }
1065         }
1066     }
1067 
1068     /**
1069      * Closes this channel when configured in non-blocking mode.
1070      *
1071      * If the channel is registered with a Selector then the close is deferred
1072      * until the channel is flushed from all Selectors.
1073      *
1074      * If the socket is connected and the channel is registered with a Selector
1075      * then the socket is shutdown for writing so that the peer reads EOF. In
1076      * addition, if SO_LINGER is set to a non-zero value then it is disabled so
1077      * that the deferred close does not wait.
1078      */
1079     private void implCloseNonBlockingMode() throws IOException {
1080         boolean connected;
1081         synchronized (stateLock) {

1122         }
1123     }
1124 
1125     @Override
1126     public void kill() {
1127         synchronized (stateLock) {
1128             if (state == ST_CLOSING) {
1129                 tryFinishClose();
1130             }
1131         }
1132     }
1133 
1134     @Override
1135     public SocketChannel shutdownInput() throws IOException {
1136         synchronized (stateLock) {
1137             ensureOpen();
1138             if (!isConnected())
1139                 throw new NotYetConnectedException();
1140             if (!isInputClosed) {
1141                 Net.shutdown(fd, Net.SHUT_RD);
1142                 long reader = readerThread;
1143                 if (NativeThread.isVirtualThread(reader)) {
1144                     Poller.stopPoll(fdVal, Net.POLLIN);
1145                 } else if (NativeThread.isKernelThread(reader)) {
1146                     NativeThread.signal(reader);
1147                 }
1148                 isInputClosed = true;
1149             }
1150             return this;
1151         }
1152     }
1153 
1154     @Override
1155     public SocketChannel shutdownOutput() throws IOException {
1156         synchronized (stateLock) {
1157             ensureOpen();
1158             if (!isConnected())
1159                 throw new NotYetConnectedException();
1160             if (!isOutputClosed) {
1161                 Net.shutdown(fd, Net.SHUT_WR);
1162                 long writer = writerThread;
1163                 if (NativeThread.isVirtualThread(writer)) {
1164                     Poller.stopPoll(fdVal, Net.POLLOUT);
1165                 } else if (NativeThread.isKernelThread(writer)) {
1166                     NativeThread.signal(writer);
1167                 }
1168                 isOutputClosed = true;
1169             }
1170             return this;
1171         }
1172     }
1173 
1174     boolean isInputOpen() {
1175         return !isInputClosed;
1176     }
1177 
1178     boolean isOutputOpen() {
1179         return !isOutputClosed;
1180     }
1181 
1182     /**
1183      * Waits for a connection attempt to finish with a timeout
1184      * @throws SocketTimeoutException if the connect timeout elapses
1185      */
1186     private boolean finishTimedConnect(long nanos) throws IOException {
1187         long startNanos = System.nanoTime();

1312 
1313                 // check if connection has been reset
1314                 if (connectionReset)
1315                     throwConnectionReset();
1316 
1317                 // check if input is shutdown
1318                 if (isInputClosed)
1319                     return IOStatus.EOF;
1320 
1321                 if (nanos > 0) {
1322                     // change socket to non-blocking
1323                     lockedConfigureBlocking(false);
1324                     try {
1325                         n = timedRead(b, off, len, nanos);
1326                     } finally {
1327                         // restore socket to blocking mode (if channel is open)
1328                         tryLockedConfigureBlocking(true);
1329                     }
1330                 } else {
1331                     // read, no timeout
1332                     configureNonBlockingIfNeeded();
1333                     n = tryRead(b, off, len);
1334                     while (IOStatus.okayToRetry(n) && isOpen()) {
1335                         park(Net.POLLIN);
1336                         n = tryRead(b, off, len);
1337                     }
1338                 }
1339             } catch (ConnectionResetException e) {
1340                 connectionReset = true;
1341                 throwConnectionReset();
1342             } finally {
1343                 endRead(true, n > 0);
1344                 if (n <= 0 && isInputClosed)
1345                     return IOStatus.EOF;
1346             }
1347             assert n > 0 || n == -1;
1348             return n;
1349         } finally {
1350             readLock.unlock();
1351         }
1352     }

1374     void blockingWriteFully(byte[] b, int off, int len) throws IOException {
1375         Objects.checkFromIndexSize(off, len, b.length);
1376         if (len == 0) {
1377             // nothing to do
1378             return;
1379         }
1380 
1381         writeLock.lock();
1382         try {
1383             ensureOpenAndConnected();
1384 
1385             // check that channel is configured blocking
1386             if (!isBlocking())
1387                 throw new IllegalBlockingModeException();
1388 
1389             // loop until all bytes have been written
1390             int pos = off;
1391             int end = off + len;
1392             try {
1393                 beginWrite(true);
1394                 configureNonBlockingIfNeeded();
1395                 while (pos < end && isOpen()) {
1396                     int size = end - pos;
1397                     int n = tryWrite(b, pos, size);
1398                     while (IOStatus.okayToRetry(n) && isOpen()) {
1399                         park(Net.POLLOUT);
1400                         n = tryWrite(b, pos, size);
1401                     }
1402                     if (n > 0) {
1403                         pos += n;
1404                     }
1405                 }
1406             } finally {
1407                 endWrite(true, pos >= end);
1408             }
1409         } finally {
1410             writeLock.unlock();
1411         }
1412     }
1413 
1414     /**
< prev index next >