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) {
206 * @throws IOException if there is an I/O error changing the blocking mode
207 */
208 private void configureNonBlockingIfNeeded(FileDescriptor fd, boolean timed)
209 throws IOException
210 {
211 if (!nonBlocking
212 && (timed || Thread.currentThread().isVirtual())) {
213 assert readLock.isHeldByCurrentThread() || writeLock.isHeldByCurrentThread();
214 IOUtil.configureBlocking(fd, false);
215 nonBlocking = true;
216 }
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);
279 park(fd, Net.POLLIN, remainingNanos);
280 n = tryRead(fd, b, off, len);
281 }
282 return n;
283 }
284
285 /**
286 * Reads bytes from the socket into the given byte array.
287 * @return the number of bytes read or -1 at EOF
288 * @throws SocketException if the socket is closed or a socket I/O error occurs
289 * @throws SocketTimeoutException if the read timeout elapses
290 */
291 private int implRead(byte[] b, int off, int len, long remainingNanos) throws IOException {
292 int n = 0;
293 FileDescriptor fd = beginRead();
294 try {
295 if (connectionReset)
296 throw new SocketException("Connection reset");
297 if (isInputClosed)
298 return -1;
299 configureNonBlockingIfNeeded(fd, remainingNanos > 0);
300 if (remainingNanos > 0) {
301 // read with timeout
302 n = timedRead(fd, b, off, len, remainingNanos);
303 } else {
304 // read, no timeout
305 n = tryRead(fd, b, off, len);
306 while (IOStatus.okayToRetry(n) && isOpen()) {
307 park(fd, Net.POLLIN);
308 n = tryRead(fd, b, off, len);
309 }
310 }
311 return n;
312 } catch (InterruptedIOException e) {
313 throw e;
314 } catch (ConnectionResetException e) {
315 connectionReset = true;
316 throw new SocketException("Connection reset");
317 } catch (IOException ioe) {
318 // throw SocketException to maintain compatibility
351 return -1;
352 // read up to MAX_BUFFER_SIZE bytes
353 int size = Math.min(len, MAX_BUFFER_SIZE);
354 int n = implRead(b, off, size, remainingNanos);
355 if (n == -1)
356 readEOF = true;
357 return n;
358 } finally {
359 readLock.unlock();
360 }
361 }
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);
403 } finally {
404 Util.offerFirstTemporaryDirectBuffer(src);
405 }
406 }
407
408 /**
409 * Writes a sequence of bytes to the socket from the given byte array.
410 * @return the number of bytes written
411 * @throws SocketException if the socket is closed or a socket I/O error occurs
412 */
413 private int implWrite(byte[] b, int off, int len) throws IOException {
414 int n = 0;
415 FileDescriptor fd = beginWrite();
416 try {
417 configureNonBlockingIfNeeded(fd, false);
418 n = tryWrite(fd, b, off, len);
419 while (IOStatus.okayToRetry(n) && isOpen()) {
420 park(fd, Net.POLLOUT);
421 n = tryWrite(fd, b, off, len);
422 }
423 return n;
424 } catch (InterruptedIOException e) {
425 throw e;
426 } catch (IOException ioe) {
427 // throw SocketException to maintain compatibility
428 throw asSocketException(ioe);
429 } finally {
430 endWrite(n > 0);
431 }
432 }
433
434 /**
435 * Writes a sequence of bytes to the socket from the given byte array.
436 * @throws SocketException if the socket is closed or a socket I/O error occurs
493 throw new SocketException("Not created");
494 if (state == ST_CONNECTING)
495 throw new SocketException("Connection in progress");
496 if (state == ST_CONNECTED)
497 throw new SocketException("Already connected");
498 if (state >= ST_CLOSING)
499 throw new SocketException("Socket closed");
500 assert false;
501 }
502 this.state = ST_CONNECTING;
503
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()) {
649
650 @Override
651 protected void listen(int backlog) throws IOException {
652 synchronized (stateLock) {
653 ensureOpen();
654 if (localport == 0)
655 throw new SocketException("Not bound");
656 Net.listen(fd, backlog < 1 ? 50 : backlog);
657 }
658 }
659
660 /**
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 {
1126 if (!Net.isReusePortAvailable())
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 Thread readerThread;
112 private Thread 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) {
206 * @throws IOException if there is an I/O error changing the blocking mode
207 */
208 private void configureNonBlockingIfNeeded(FileDescriptor fd, boolean timed)
209 throws IOException
210 {
211 if (!nonBlocking
212 && (timed || Thread.currentThread().isVirtual())) {
213 assert readLock.isHeldByCurrentThread() || writeLock.isHeldByCurrentThread();
214 IOUtil.configureBlocking(fd, false);
215 nonBlocking = true;
216 }
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.threadToSignal();
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);
279 park(fd, Net.POLLIN, remainingNanos);
280 n = tryRead(fd, b, off, len);
281 }
282 return n;
283 }
284
285 /**
286 * Reads bytes from the socket into the given byte array.
287 * @return the number of bytes read or -1 at EOF
288 * @throws SocketException if the socket is closed or a socket I/O error occurs
289 * @throws SocketTimeoutException if the read timeout elapses
290 */
291 private int implRead(byte[] b, int off, int len, long remainingNanos) throws IOException {
292 int n = 0;
293 FileDescriptor fd = beginRead();
294 try {
295 if (connectionReset)
296 throw new SocketException("Connection reset");
297 if (isInputClosed)
298 return -1;
299
300 // experimental
301 if (Poller.supportReadOps() && Thread.currentThread().isVirtual()) {
302 n = Poller.read(fdVal(fd), b, off, len, remainingNanos, this::isOpen);
303 if (n != IOStatus.UNAVAILABLE) return n;
304 }
305
306 configureNonBlockingIfNeeded(fd, remainingNanos > 0);
307 if (remainingNanos > 0) {
308 // read with timeout
309 n = timedRead(fd, b, off, len, remainingNanos);
310 } else {
311 // read, no timeout
312 n = tryRead(fd, b, off, len);
313 while (IOStatus.okayToRetry(n) && isOpen()) {
314 park(fd, Net.POLLIN);
315 n = tryRead(fd, b, off, len);
316 }
317 }
318 return n;
319 } catch (InterruptedIOException e) {
320 throw e;
321 } catch (ConnectionResetException e) {
322 connectionReset = true;
323 throw new SocketException("Connection reset");
324 } catch (IOException ioe) {
325 // throw SocketException to maintain compatibility
358 return -1;
359 // read up to MAX_BUFFER_SIZE bytes
360 int size = Math.min(len, MAX_BUFFER_SIZE);
361 int n = implRead(b, off, size, remainingNanos);
362 if (n == -1)
363 readEOF = true;
364 return n;
365 } finally {
366 readLock.unlock();
367 }
368 }
369 }
370
371 /**
372 * Marks the beginning of a write operation that might block.
373 * @throws SocketException if the socket is closed or not connected
374 */
375 private FileDescriptor beginWrite() throws SocketException {
376 synchronized (stateLock) {
377 ensureOpenAndConnected();
378 writerThread = NativeThread.threadToSignal();
379 return fd;
380 }
381 }
382
383 /**
384 * Marks the end of a write operation that may have blocked.
385 * @throws SocketException is the socket is closed
386 */
387 private void endWrite(boolean completed) throws SocketException {
388 synchronized (stateLock) {
389 writerThread = null;
390 int state = this.state;
391 if (state == ST_CLOSING)
392 tryFinishClose();
393 if (!completed && state >= ST_CLOSING)
394 throw new SocketException("Socket closed");
395 }
396 }
397
398 /**
399 * Attempts to write a sequence of bytes to the socket from the given
400 * byte array.
401 */
402 private int tryWrite(FileDescriptor fd, byte[] b, int off, int len)
403 throws IOException
404 {
405 ByteBuffer src = Util.getTemporaryDirectBuffer(len);
406 assert src.position() == 0;
407 try {
408 src.put(b, off, len);
409 return nd.write(fd, ((DirectBuffer)src).address(), len);
410 } finally {
411 Util.offerFirstTemporaryDirectBuffer(src);
412 }
413 }
414
415 /**
416 * Writes a sequence of bytes to the socket from the given byte array.
417 * @return the number of bytes written
418 * @throws SocketException if the socket is closed or a socket I/O error occurs
419 */
420 private int implWrite(byte[] b, int off, int len) throws IOException {
421 int n = 0;
422 FileDescriptor fd = beginWrite();
423 try {
424
425 // experimental
426 if (Poller.supportWriteOps() && Thread.currentThread().isVirtual()) {
427 n = Poller.write(fdVal(fd), b, off, len, this::isOpen);
428 if (n != IOStatus.UNAVAILABLE) return n;
429 }
430
431 configureNonBlockingIfNeeded(fd, false);
432 n = tryWrite(fd, b, off, len);
433 while (IOStatus.okayToRetry(n) && isOpen()) {
434 park(fd, Net.POLLOUT);
435 n = tryWrite(fd, b, off, len);
436 }
437 return n;
438 } catch (InterruptedIOException e) {
439 throw e;
440 } catch (IOException ioe) {
441 // throw SocketException to maintain compatibility
442 throw asSocketException(ioe);
443 } finally {
444 endWrite(n > 0);
445 }
446 }
447
448 /**
449 * Writes a sequence of bytes to the socket from the given byte array.
450 * @throws SocketException if the socket is closed or a socket I/O error occurs
507 throw new SocketException("Not created");
508 if (state == ST_CONNECTING)
509 throw new SocketException("Connection in progress");
510 if (state == ST_CONNECTED)
511 throw new SocketException("Already connected");
512 if (state >= ST_CLOSING)
513 throw new SocketException("Socket closed");
514 assert false;
515 }
516 this.state = ST_CONNECTING;
517
518 // invoke beforeTcpConnect hook if not already bound
519 if (localport == 0) {
520 NetHooks.beforeTcpConnect(fd, address, port);
521 }
522
523 // save the remote address/port
524 this.address = address;
525 this.port = port;
526
527 readerThread = NativeThread.threadToSignal();
528 return fd;
529 }
530 }
531
532 /**
533 * Marks the end of a connect operation that may have blocked.
534 * @throws SocketException is the socket is closed
535 */
536 private void endConnect(FileDescriptor fd, boolean completed) throws IOException {
537 synchronized (stateLock) {
538 readerThread = null;
539 int state = this.state;
540 if (state == ST_CLOSING)
541 tryFinishClose();
542 if (completed && state == ST_CONNECTING) {
543 this.state = ST_CONNECTED;
544 localport = Net.localAddress(fd).getPort();
545 } else if (!completed && state >= ST_CLOSING) {
546 throw new SocketException("Socket closed");
547 }
548 }
549 }
550
551 /**
552 * Waits for a connection attempt to finish with a timeout
553 * @throws SocketTimeoutException if the connect timeout elapses
554 */
555 private boolean timedFinishConnect(FileDescriptor fd, long nanos) throws IOException {
556 long startNanos = System.nanoTime();
557 boolean polled = Net.pollConnectNow(fd);
558 while (!polled && isOpen()) {
663
664 @Override
665 protected void listen(int backlog) throws IOException {
666 synchronized (stateLock) {
667 ensureOpen();
668 if (localport == 0)
669 throw new SocketException("Not bound");
670 Net.listen(fd, backlog < 1 ? 50 : backlog);
671 }
672 }
673
674 /**
675 * Marks the beginning of an accept operation that might block.
676 * @throws SocketException if the socket is closed
677 */
678 private FileDescriptor beginAccept() throws SocketException {
679 synchronized (stateLock) {
680 ensureOpen();
681 if (localport == 0)
682 throw new SocketException("Not bound");
683 readerThread = NativeThread.threadToSignal();
684 return fd;
685 }
686 }
687
688 /**
689 * Marks the end of an accept operation that may have blocked.
690 * @throws SocketException is the socket is closed
691 */
692 private void endAccept(boolean completed) throws SocketException {
693 synchronized (stateLock) {
694 int state = this.state;
695 readerThread = null;
696 if (state == ST_CLOSING)
697 tryFinishClose();
698 if (!completed && state >= ST_CLOSING)
699 throw new SocketException("Socket closed");
700 }
701 }
702
703 /**
704 * Accepts a new connection with a timeout.
705 * @throws SocketTimeoutException if the accept timeout elapses
706 */
707 private int timedAccept(FileDescriptor fd,
708 FileDescriptor newfd,
709 InetSocketAddress[] isaa,
710 long nanos)
711 throws IOException
712 {
713 long startNanos = System.nanoTime();
714 int n = Net.accept(fd, newfd, isaa);
715 while (n == IOStatus.UNAVAILABLE && isOpen()) {
841 };
842 }
843
844 @Override
845 protected int available() throws IOException {
846 synchronized (stateLock) {
847 ensureOpenAndConnected();
848 if (isInputClosed) {
849 return 0;
850 } else {
851 return Net.available(fd);
852 }
853 }
854 }
855
856 /**
857 * Closes the socket if there are no I/O operations in progress.
858 */
859 private boolean tryClose() throws IOException {
860 assert Thread.holdsLock(stateLock) && state == ST_CLOSING;
861 if (readerThread == null && writerThread == null) {
862 try {
863 cleaner.clean();
864 } catch (UncheckedIOException ioe) {
865 throw ioe.getCause();
866 } finally {
867 state = ST_CLOSED;
868 }
869 return true;
870 } else {
871 return false;
872 }
873 }
874
875 /**
876 * Invokes tryClose to attempt to close the socket.
877 *
878 * This method is used for deferred closing by I/O operations.
879 */
880 private void tryFinishClose() {
881 try {
1140 if (!Net.isReusePortAvailable())
1141 throw new SocketException("SO_REUSEPORT not supported");
1142 return Net.getSocketOption(fd, StandardSocketOptions.SO_REUSEPORT);
1143 default:
1144 throw new SocketException("Unknown option " + opt);
1145 }
1146 } catch (SocketException e) {
1147 throw e;
1148 } catch (IllegalArgumentException | IOException e) {
1149 throw asSocketException(e);
1150 }
1151 }
1152 }
1153
1154 @Override
1155 protected void shutdownInput() throws IOException {
1156 synchronized (stateLock) {
1157 ensureOpenAndConnected();
1158 if (!isInputClosed) {
1159 Net.shutdown(fd, Net.SHUT_RD);
1160 if (readerThread != null && readerThread.isVirtual()) {
1161 Poller.stopPoll(readerThread);
1162 }
1163 isInputClosed = true;
1164 }
1165 }
1166 }
1167
1168 @Override
1169 protected void shutdownOutput() throws IOException {
1170 synchronized (stateLock) {
1171 ensureOpenAndConnected();
1172 if (!isOutputClosed) {
1173 Net.shutdown(fd, Net.SHUT_WR);
1174 if (writerThread != null && writerThread.isVirtual()) {
1175 Poller.stopPoll(writerThread);
1176 }
1177 isOutputClosed = true;
1178 }
1179 }
1180 }
1181
1182 @Override
1183 protected boolean supportsUrgentData() {
1184 return true;
1185 }
1186
1187 @Override
1188 protected void sendUrgentData(int data) throws IOException {
1189 writeLock.lock();
1190 try {
1191 int n = 0;
1192 FileDescriptor fd = beginWrite();
1193 try {
1194 configureNonBlockingIfNeeded(fd, false);
1195 do {
|