90
91 // Lock held when writing
92 private final ReentrantLock writeLock = new ReentrantLock();
93
94 // The stateLock for read/changing state
95 private final Object stateLock = new Object();
96 private static final int ST_NEW = 0;
97 private static final int ST_UNCONNECTED = 1;
98 private static final int ST_CONNECTING = 2;
99 private static final int ST_CONNECTED = 3;
100 private static final int ST_CLOSING = 4;
101 private static final int ST_CLOSED = 5;
102 private volatile int state; // need stateLock to change
103
104 private Cleanable cleaner;
105
106 // set to true when the socket is in non-blocking mode
107 private volatile boolean nonBlocking;
108
109 // used by connect/read/write/accept, protected by stateLock
110 private long readerThread;
111 private long writerThread;
112
113 // used when SO_REUSEADDR is emulated, protected by stateLock
114 private boolean isReuseAddress;
115
116 // read or accept timeout in millis
117 private volatile int timeout;
118
119 // flags to indicate if the connection is shutdown for input and output
120 private volatile boolean isInputClosed;
121 private volatile boolean isOutputClosed;
122
123 // used by read to emulate legacy behavior, protected by readLock
124 private boolean readEOF;
125 private boolean connectionReset;
126
127 /**
128 * Creates an instance of this SocketImpl.
129 * @param server true if this is a SocketImpl for a ServerSocket
130 */
131 public NioSocketImpl(boolean server) {
205 * @throws IOException if there is an I/O error changing the blocking mode
206 */
207 private void configureNonBlockingIfNeeded(FileDescriptor fd, boolean timed)
208 throws IOException
209 {
210 if (!nonBlocking
211 && (timed || Thread.currentThread().isVirtual())) {
212 assert readLock.isHeldByCurrentThread() || writeLock.isHeldByCurrentThread();
213 IOUtil.configureBlocking(fd, false);
214 nonBlocking = true;
215 }
216 }
217
218 /**
219 * Marks the beginning of a read operation that might block.
220 * @throws SocketException if the socket is closed or not connected
221 */
222 private FileDescriptor beginRead() throws SocketException {
223 synchronized (stateLock) {
224 ensureOpenAndConnected();
225 readerThread = NativeThread.current();
226 return fd;
227 }
228 }
229
230 /**
231 * Marks the end of a read operation that may have blocked.
232 * @throws SocketException is the socket is closed
233 */
234 private void endRead(boolean completed) throws SocketException {
235 synchronized (stateLock) {
236 readerThread = 0;
237 int state = this.state;
238 if (state == ST_CLOSING)
239 tryFinishClose();
240 if (!completed && state >= ST_CLOSING)
241 throw new SocketException("Socket closed");
242 }
243 }
244
245 /**
246 * Attempts to read bytes from the socket into the given byte array.
247 */
248 private int tryRead(FileDescriptor fd, byte[] b, int off, int len)
249 throws IOException
250 {
251 ByteBuffer dst = Util.getTemporaryDirectBuffer(len);
252 assert dst.position() == 0;
253 try {
254 int n = nd.read(fd, ((DirectBuffer)dst).address(), len);
255 if (n > 0) {
256 dst.get(b, off, n);
278 park(fd, Net.POLLIN, remainingNanos);
279 n = tryRead(fd, b, off, len);
280 }
281 return n;
282 }
283
284 /**
285 * Reads bytes from the socket into the given byte array.
286 * @return the number of bytes read or -1 at EOF
287 * @throws SocketException if the socket is closed or a socket I/O error occurs
288 * @throws SocketTimeoutException if the read timeout elapses
289 */
290 private int implRead(byte[] b, int off, int len, long remainingNanos) throws IOException {
291 int n = 0;
292 FileDescriptor fd = beginRead();
293 try {
294 if (connectionReset)
295 throw new SocketException("Connection reset");
296 if (isInputClosed)
297 return -1;
298 configureNonBlockingIfNeeded(fd, remainingNanos > 0);
299 if (remainingNanos > 0) {
300 // read with timeout
301 n = timedRead(fd, b, off, len, remainingNanos);
302 } else {
303 // read, no timeout
304 n = tryRead(fd, b, off, len);
305 while (IOStatus.okayToRetry(n) && isOpen()) {
306 park(fd, Net.POLLIN);
307 n = tryRead(fd, b, off, len);
308 }
309 }
310 return n;
311 } catch (InterruptedIOException e) {
312 throw e;
313 } catch (ConnectionResetException e) {
314 connectionReset = true;
315 throw new SocketException("Connection reset");
316 } catch (IOException ioe) {
317 // throw SocketException to maintain compatibility
350 return -1;
351 // read up to MAX_BUFFER_SIZE bytes
352 int size = Math.min(len, MAX_BUFFER_SIZE);
353 int n = implRead(b, off, size, remainingNanos);
354 if (n == -1)
355 readEOF = true;
356 return n;
357 } finally {
358 readLock.unlock();
359 }
360 }
361 }
362
363 /**
364 * Marks the beginning of a write operation that might block.
365 * @throws SocketException if the socket is closed or not connected
366 */
367 private FileDescriptor beginWrite() throws SocketException {
368 synchronized (stateLock) {
369 ensureOpenAndConnected();
370 writerThread = NativeThread.current();
371 return fd;
372 }
373 }
374
375 /**
376 * Marks the end of a write operation that may have blocked.
377 * @throws SocketException is the socket is closed
378 */
379 private void endWrite(boolean completed) throws SocketException {
380 synchronized (stateLock) {
381 writerThread = 0;
382 int state = this.state;
383 if (state == ST_CLOSING)
384 tryFinishClose();
385 if (!completed && state >= ST_CLOSING)
386 throw new SocketException("Socket closed");
387 }
388 }
389
390 /**
391 * Attempts to write a sequence of bytes to the socket from the given
392 * byte array.
393 */
394 private int tryWrite(FileDescriptor fd, byte[] b, int off, int len)
395 throws IOException
396 {
397 ByteBuffer src = Util.getTemporaryDirectBuffer(len);
398 assert src.position() == 0;
399 try {
400 src.put(b, off, len);
401 return nd.write(fd, ((DirectBuffer)src).address(), len);
402 } finally {
403 Util.offerFirstTemporaryDirectBuffer(src);
404 }
405 }
406
407 /**
408 * Writes a sequence of bytes to the socket from the given byte array.
409 * @return the number of bytes written
410 * @throws SocketException if the socket is closed or a socket I/O error occurs
411 */
412 private int implWrite(byte[] b, int off, int len) throws IOException {
413 int n = 0;
414 FileDescriptor fd = beginWrite();
415 try {
416 configureNonBlockingIfNeeded(fd, false);
417 n = tryWrite(fd, b, off, len);
418 while (IOStatus.okayToRetry(n) && isOpen()) {
419 park(fd, Net.POLLOUT);
420 n = tryWrite(fd, b, off, len);
421 }
422 return n;
423 } catch (InterruptedIOException e) {
424 throw e;
425 } catch (IOException ioe) {
426 // throw SocketException to maintain compatibility
427 throw asSocketException(ioe);
428 } finally {
429 endWrite(n > 0);
430 }
431 }
432
433 /**
434 * Writes a sequence of bytes to the socket from the given byte array.
435 * @throws SocketException if the socket is closed or a socket I/O error occurs
487 {
488 synchronized (stateLock) {
489 int state = this.state;
490 if (state != ST_UNCONNECTED) {
491 if (state == ST_NEW)
492 throw new SocketException("Not created");
493 if (state == ST_CONNECTING)
494 throw new SocketException("Connection in progress");
495 if (state == ST_CONNECTED)
496 throw new SocketException("Already connected");
497 if (state >= ST_CLOSING)
498 throw new SocketException("Socket closed");
499 assert false;
500 }
501 this.state = ST_CONNECTING;
502
503 // save the remote address/port
504 this.address = address;
505 this.port = port;
506
507 readerThread = NativeThread.current();
508 return fd;
509 }
510 }
511
512 /**
513 * Marks the end of a connect operation that may have blocked.
514 * @throws SocketException is the socket is closed
515 */
516 private void endConnect(FileDescriptor fd, boolean completed) throws IOException {
517 synchronized (stateLock) {
518 readerThread = 0;
519 int state = this.state;
520 if (state == ST_CLOSING)
521 tryFinishClose();
522 if (completed && state == ST_CONNECTING) {
523 this.state = ST_CONNECTED;
524 localport = Net.localAddress(fd).getPort();
525 } else if (!completed && state >= ST_CLOSING) {
526 throw new SocketException("Socket closed");
527 }
528 }
529 }
530
531 /**
532 * Waits for a connection attempt to finish with a timeout
533 * @throws SocketTimeoutException if the connect timeout elapses
534 */
535 private boolean timedFinishConnect(FileDescriptor fd, long nanos) throws IOException {
536 long startNanos = System.nanoTime();
537 boolean polled = Net.pollConnectNow(fd);
538 while (!polled && isOpen()) {
642
643 @Override
644 protected void listen(int backlog) throws IOException {
645 synchronized (stateLock) {
646 ensureOpen();
647 if (localport == 0)
648 throw new SocketException("Not bound");
649 Net.listen(fd, backlog < 1 ? 50 : backlog);
650 }
651 }
652
653 /**
654 * Marks the beginning of an accept operation that might block.
655 * @throws SocketException if the socket is closed
656 */
657 private FileDescriptor beginAccept() throws SocketException {
658 synchronized (stateLock) {
659 ensureOpen();
660 if (localport == 0)
661 throw new SocketException("Not bound");
662 readerThread = NativeThread.current();
663 return fd;
664 }
665 }
666
667 /**
668 * Marks the end of an accept operation that may have blocked.
669 * @throws SocketException is the socket is closed
670 */
671 private void endAccept(boolean completed) throws SocketException {
672 synchronized (stateLock) {
673 int state = this.state;
674 readerThread = 0;
675 if (state == ST_CLOSING)
676 tryFinishClose();
677 if (!completed && state >= ST_CLOSING)
678 throw new SocketException("Socket closed");
679 }
680 }
681
682 /**
683 * Accepts a new connection with a timeout.
684 * @throws SocketTimeoutException if the accept timeout elapses
685 */
686 private int timedAccept(FileDescriptor fd,
687 FileDescriptor newfd,
688 InetSocketAddress[] isaa,
689 long nanos)
690 throws IOException
691 {
692 long startNanos = System.nanoTime();
693 int n = Net.accept(fd, newfd, isaa);
694 while (n == IOStatus.UNAVAILABLE && isOpen()) {
820 };
821 }
822
823 @Override
824 protected int available() throws IOException {
825 synchronized (stateLock) {
826 ensureOpenAndConnected();
827 if (isInputClosed) {
828 return 0;
829 } else {
830 return Net.available(fd);
831 }
832 }
833 }
834
835 /**
836 * Closes the socket if there are no I/O operations in progress.
837 */
838 private boolean tryClose() throws IOException {
839 assert Thread.holdsLock(stateLock) && state == ST_CLOSING;
840 if (readerThread == 0 && writerThread == 0) {
841 try {
842 cleaner.clean();
843 } catch (UncheckedIOException ioe) {
844 throw ioe.getCause();
845 } finally {
846 state = ST_CLOSED;
847 }
848 return true;
849 } else {
850 return false;
851 }
852 }
853
854 /**
855 * Invokes tryClose to attempt to close the socket.
856 *
857 * This method is used for deferred closing by I/O operations.
858 */
859 private void tryFinishClose() {
860 try {
1119 if (!Net.isReusePortAvailable())
1120 throw new SocketException("SO_REUSEPORT not supported");
1121 return Net.getSocketOption(fd, StandardSocketOptions.SO_REUSEPORT);
1122 default:
1123 throw new SocketException("Unknown option " + opt);
1124 }
1125 } catch (SocketException e) {
1126 throw e;
1127 } catch (IllegalArgumentException | IOException e) {
1128 throw asSocketException(e);
1129 }
1130 }
1131 }
1132
1133 @Override
1134 protected void shutdownInput() throws IOException {
1135 synchronized (stateLock) {
1136 ensureOpenAndConnected();
1137 if (!isInputClosed) {
1138 Net.shutdown(fd, Net.SHUT_RD);
1139 if (NativeThread.isVirtualThread(readerThread)) {
1140 Poller.stopPoll(fdVal(fd), Net.POLLIN);
1141 }
1142 isInputClosed = true;
1143 }
1144 }
1145 }
1146
1147 @Override
1148 protected void shutdownOutput() throws IOException {
1149 synchronized (stateLock) {
1150 ensureOpenAndConnected();
1151 if (!isOutputClosed) {
1152 Net.shutdown(fd, Net.SHUT_WR);
1153 if (NativeThread.isVirtualThread(writerThread)) {
1154 Poller.stopPoll(fdVal(fd), Net.POLLOUT);
1155 }
1156 isOutputClosed = true;
1157 }
1158 }
1159 }
1160
1161 @Override
1162 protected boolean supportsUrgentData() {
1163 return true;
1164 }
1165
1166 @Override
1167 protected void sendUrgentData(int data) throws IOException {
1168 writeLock.lock();
1169 try {
1170 int n = 0;
1171 FileDescriptor fd = beginWrite();
1172 try {
1173 configureNonBlockingIfNeeded(fd, false);
1174 do {
|
90
91 // Lock held when writing
92 private final ReentrantLock writeLock = new ReentrantLock();
93
94 // The stateLock for read/changing state
95 private final Object stateLock = new Object();
96 private static final int ST_NEW = 0;
97 private static final int ST_UNCONNECTED = 1;
98 private static final int ST_CONNECTING = 2;
99 private static final int ST_CONNECTED = 3;
100 private static final int ST_CLOSING = 4;
101 private static final int ST_CLOSED = 5;
102 private volatile int state; // need stateLock to change
103
104 private Cleanable cleaner;
105
106 // set to true when the socket is in non-blocking mode
107 private volatile boolean nonBlocking;
108
109 // used by connect/read/write/accept, protected by stateLock
110 private Thread readerThread;
111 private Thread writerThread;
112
113 // used when SO_REUSEADDR is emulated, protected by stateLock
114 private boolean isReuseAddress;
115
116 // read or accept timeout in millis
117 private volatile int timeout;
118
119 // flags to indicate if the connection is shutdown for input and output
120 private volatile boolean isInputClosed;
121 private volatile boolean isOutputClosed;
122
123 // used by read to emulate legacy behavior, protected by readLock
124 private boolean readEOF;
125 private boolean connectionReset;
126
127 /**
128 * Creates an instance of this SocketImpl.
129 * @param server true if this is a SocketImpl for a ServerSocket
130 */
131 public NioSocketImpl(boolean server) {
205 * @throws IOException if there is an I/O error changing the blocking mode
206 */
207 private void configureNonBlockingIfNeeded(FileDescriptor fd, boolean timed)
208 throws IOException
209 {
210 if (!nonBlocking
211 && (timed || Thread.currentThread().isVirtual())) {
212 assert readLock.isHeldByCurrentThread() || writeLock.isHeldByCurrentThread();
213 IOUtil.configureBlocking(fd, false);
214 nonBlocking = true;
215 }
216 }
217
218 /**
219 * Marks the beginning of a read operation that might block.
220 * @throws SocketException if the socket is closed or not connected
221 */
222 private FileDescriptor beginRead() throws SocketException {
223 synchronized (stateLock) {
224 ensureOpenAndConnected();
225 readerThread = NativeThread.threadToSignal();
226 return fd;
227 }
228 }
229
230 /**
231 * Marks the end of a read operation that may have blocked.
232 * @throws SocketException is the socket is closed
233 */
234 private void endRead(boolean completed) throws SocketException {
235 synchronized (stateLock) {
236 readerThread = null;
237 int state = this.state;
238 if (state == ST_CLOSING)
239 tryFinishClose();
240 if (!completed && state >= ST_CLOSING)
241 throw new SocketException("Socket closed");
242 }
243 }
244
245 /**
246 * Attempts to read bytes from the socket into the given byte array.
247 */
248 private int tryRead(FileDescriptor fd, byte[] b, int off, int len)
249 throws IOException
250 {
251 ByteBuffer dst = Util.getTemporaryDirectBuffer(len);
252 assert dst.position() == 0;
253 try {
254 int n = nd.read(fd, ((DirectBuffer)dst).address(), len);
255 if (n > 0) {
256 dst.get(b, off, n);
278 park(fd, Net.POLLIN, remainingNanos);
279 n = tryRead(fd, b, off, len);
280 }
281 return n;
282 }
283
284 /**
285 * Reads bytes from the socket into the given byte array.
286 * @return the number of bytes read or -1 at EOF
287 * @throws SocketException if the socket is closed or a socket I/O error occurs
288 * @throws SocketTimeoutException if the read timeout elapses
289 */
290 private int implRead(byte[] b, int off, int len, long remainingNanos) throws IOException {
291 int n = 0;
292 FileDescriptor fd = beginRead();
293 try {
294 if (connectionReset)
295 throw new SocketException("Connection reset");
296 if (isInputClosed)
297 return -1;
298
299 // experimental
300 if (Poller.supportReadOps() && Thread.currentThread().isVirtual()) {
301 n = Poller.read(fdVal(fd), b, off, len, remainingNanos, this::isOpen);
302 if (n != IOStatus.UNAVAILABLE) return n;
303 }
304
305 configureNonBlockingIfNeeded(fd, remainingNanos > 0);
306 if (remainingNanos > 0) {
307 // read with timeout
308 n = timedRead(fd, b, off, len, remainingNanos);
309 } else {
310 // read, no timeout
311 n = tryRead(fd, b, off, len);
312 while (IOStatus.okayToRetry(n) && isOpen()) {
313 park(fd, Net.POLLIN);
314 n = tryRead(fd, b, off, len);
315 }
316 }
317 return n;
318 } catch (InterruptedIOException e) {
319 throw e;
320 } catch (ConnectionResetException e) {
321 connectionReset = true;
322 throw new SocketException("Connection reset");
323 } catch (IOException ioe) {
324 // throw SocketException to maintain compatibility
357 return -1;
358 // read up to MAX_BUFFER_SIZE bytes
359 int size = Math.min(len, MAX_BUFFER_SIZE);
360 int n = implRead(b, off, size, remainingNanos);
361 if (n == -1)
362 readEOF = true;
363 return n;
364 } finally {
365 readLock.unlock();
366 }
367 }
368 }
369
370 /**
371 * Marks the beginning of a write operation that might block.
372 * @throws SocketException if the socket is closed or not connected
373 */
374 private FileDescriptor beginWrite() throws SocketException {
375 synchronized (stateLock) {
376 ensureOpenAndConnected();
377 writerThread = NativeThread.threadToSignal();
378 return fd;
379 }
380 }
381
382 /**
383 * Marks the end of a write operation that may have blocked.
384 * @throws SocketException is the socket is closed
385 */
386 private void endWrite(boolean completed) throws SocketException {
387 synchronized (stateLock) {
388 writerThread = null;
389 int state = this.state;
390 if (state == ST_CLOSING)
391 tryFinishClose();
392 if (!completed && state >= ST_CLOSING)
393 throw new SocketException("Socket closed");
394 }
395 }
396
397 /**
398 * Attempts to write a sequence of bytes to the socket from the given
399 * byte array.
400 */
401 private int tryWrite(FileDescriptor fd, byte[] b, int off, int len)
402 throws IOException
403 {
404 ByteBuffer src = Util.getTemporaryDirectBuffer(len);
405 assert src.position() == 0;
406 try {
407 src.put(b, off, len);
408 return nd.write(fd, ((DirectBuffer)src).address(), len);
409 } finally {
410 Util.offerFirstTemporaryDirectBuffer(src);
411 }
412 }
413
414 /**
415 * Writes a sequence of bytes to the socket from the given byte array.
416 * @return the number of bytes written
417 * @throws SocketException if the socket is closed or a socket I/O error occurs
418 */
419 private int implWrite(byte[] b, int off, int len) throws IOException {
420 int n = 0;
421 FileDescriptor fd = beginWrite();
422 try {
423
424 // experimental
425 if (Poller.supportWriteOps() && Thread.currentThread().isVirtual()) {
426 n = Poller.write(fdVal(fd), b, off, len, this::isOpen);
427 if (n != IOStatus.UNAVAILABLE) return n;
428 }
429
430 configureNonBlockingIfNeeded(fd, false);
431 n = tryWrite(fd, b, off, len);
432 while (IOStatus.okayToRetry(n) && isOpen()) {
433 park(fd, Net.POLLOUT);
434 n = tryWrite(fd, b, off, len);
435 }
436 return n;
437 } catch (InterruptedIOException e) {
438 throw e;
439 } catch (IOException ioe) {
440 // throw SocketException to maintain compatibility
441 throw asSocketException(ioe);
442 } finally {
443 endWrite(n > 0);
444 }
445 }
446
447 /**
448 * Writes a sequence of bytes to the socket from the given byte array.
449 * @throws SocketException if the socket is closed or a socket I/O error occurs
501 {
502 synchronized (stateLock) {
503 int state = this.state;
504 if (state != ST_UNCONNECTED) {
505 if (state == ST_NEW)
506 throw new SocketException("Not created");
507 if (state == ST_CONNECTING)
508 throw new SocketException("Connection in progress");
509 if (state == ST_CONNECTED)
510 throw new SocketException("Already connected");
511 if (state >= ST_CLOSING)
512 throw new SocketException("Socket closed");
513 assert false;
514 }
515 this.state = ST_CONNECTING;
516
517 // save the remote address/port
518 this.address = address;
519 this.port = port;
520
521 readerThread = NativeThread.threadToSignal();
522 return fd;
523 }
524 }
525
526 /**
527 * Marks the end of a connect operation that may have blocked.
528 * @throws SocketException is the socket is closed
529 */
530 private void endConnect(FileDescriptor fd, boolean completed) throws IOException {
531 synchronized (stateLock) {
532 readerThread = null;
533 int state = this.state;
534 if (state == ST_CLOSING)
535 tryFinishClose();
536 if (completed && state == ST_CONNECTING) {
537 this.state = ST_CONNECTED;
538 localport = Net.localAddress(fd).getPort();
539 } else if (!completed && state >= ST_CLOSING) {
540 throw new SocketException("Socket closed");
541 }
542 }
543 }
544
545 /**
546 * Waits for a connection attempt to finish with a timeout
547 * @throws SocketTimeoutException if the connect timeout elapses
548 */
549 private boolean timedFinishConnect(FileDescriptor fd, long nanos) throws IOException {
550 long startNanos = System.nanoTime();
551 boolean polled = Net.pollConnectNow(fd);
552 while (!polled && isOpen()) {
656
657 @Override
658 protected void listen(int backlog) throws IOException {
659 synchronized (stateLock) {
660 ensureOpen();
661 if (localport == 0)
662 throw new SocketException("Not bound");
663 Net.listen(fd, backlog < 1 ? 50 : backlog);
664 }
665 }
666
667 /**
668 * Marks the beginning of an accept operation that might block.
669 * @throws SocketException if the socket is closed
670 */
671 private FileDescriptor beginAccept() throws SocketException {
672 synchronized (stateLock) {
673 ensureOpen();
674 if (localport == 0)
675 throw new SocketException("Not bound");
676 readerThread = NativeThread.threadToSignal();
677 return fd;
678 }
679 }
680
681 /**
682 * Marks the end of an accept operation that may have blocked.
683 * @throws SocketException is the socket is closed
684 */
685 private void endAccept(boolean completed) throws SocketException {
686 synchronized (stateLock) {
687 int state = this.state;
688 readerThread = null;
689 if (state == ST_CLOSING)
690 tryFinishClose();
691 if (!completed && state >= ST_CLOSING)
692 throw new SocketException("Socket closed");
693 }
694 }
695
696 /**
697 * Accepts a new connection with a timeout.
698 * @throws SocketTimeoutException if the accept timeout elapses
699 */
700 private int timedAccept(FileDescriptor fd,
701 FileDescriptor newfd,
702 InetSocketAddress[] isaa,
703 long nanos)
704 throws IOException
705 {
706 long startNanos = System.nanoTime();
707 int n = Net.accept(fd, newfd, isaa);
708 while (n == IOStatus.UNAVAILABLE && isOpen()) {
834 };
835 }
836
837 @Override
838 protected int available() throws IOException {
839 synchronized (stateLock) {
840 ensureOpenAndConnected();
841 if (isInputClosed) {
842 return 0;
843 } else {
844 return Net.available(fd);
845 }
846 }
847 }
848
849 /**
850 * Closes the socket if there are no I/O operations in progress.
851 */
852 private boolean tryClose() throws IOException {
853 assert Thread.holdsLock(stateLock) && state == ST_CLOSING;
854 if (readerThread == null && writerThread == null) {
855 try {
856 cleaner.clean();
857 } catch (UncheckedIOException ioe) {
858 throw ioe.getCause();
859 } finally {
860 state = ST_CLOSED;
861 }
862 return true;
863 } else {
864 return false;
865 }
866 }
867
868 /**
869 * Invokes tryClose to attempt to close the socket.
870 *
871 * This method is used for deferred closing by I/O operations.
872 */
873 private void tryFinishClose() {
874 try {
1133 if (!Net.isReusePortAvailable())
1134 throw new SocketException("SO_REUSEPORT not supported");
1135 return Net.getSocketOption(fd, StandardSocketOptions.SO_REUSEPORT);
1136 default:
1137 throw new SocketException("Unknown option " + opt);
1138 }
1139 } catch (SocketException e) {
1140 throw e;
1141 } catch (IllegalArgumentException | IOException e) {
1142 throw asSocketException(e);
1143 }
1144 }
1145 }
1146
1147 @Override
1148 protected void shutdownInput() throws IOException {
1149 synchronized (stateLock) {
1150 ensureOpenAndConnected();
1151 if (!isInputClosed) {
1152 Net.shutdown(fd, Net.SHUT_RD);
1153 if (readerThread != null && readerThread.isVirtual()) {
1154 Poller.stopPoll(readerThread);
1155 }
1156 isInputClosed = true;
1157 }
1158 }
1159 }
1160
1161 @Override
1162 protected void shutdownOutput() throws IOException {
1163 synchronized (stateLock) {
1164 ensureOpenAndConnected();
1165 if (!isOutputClosed) {
1166 Net.shutdown(fd, Net.SHUT_WR);
1167 if (writerThread != null && writerThread.isVirtual()) {
1168 Poller.stopPoll(writerThread);
1169 }
1170 isOutputClosed = true;
1171 }
1172 }
1173 }
1174
1175 @Override
1176 protected boolean supportsUrgentData() {
1177 return true;
1178 }
1179
1180 @Override
1181 protected void sendUrgentData(int data) throws IOException {
1182 writeLock.lock();
1183 try {
1184 int n = 0;
1185 FileDescriptor fd = beginWrite();
1186 try {
1187 configureNonBlockingIfNeeded(fd, false);
1188 do {
|