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);
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 SocketException ex = null;
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 } catch (InterruptedIOException e) {
312 throw e;
313 } catch (ConnectionResetException e) {
314 connectionReset = true;
315 throw new SocketException("Connection reset");
316 } catch (IOException ioe) {
317 // translate to SocketException to maintain compatibility
318 ex = asSocketException(ioe);
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.current();
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 = 0;
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 SocketException ex = null;
422 FileDescriptor fd = beginWrite();
423 try {
424 configureNonBlockingIfNeeded(fd, false);
425 n = tryWrite(fd, b, off, len);
426 while (IOStatus.okayToRetry(n) && isOpen()) {
427 park(fd, Net.POLLOUT);
428 n = tryWrite(fd, b, off, len);
429 }
430 } catch (InterruptedIOException e) {
431 throw e;
432 } catch (IOException ioe) {
433 // translate to SocketException to maintain compatibility
434 ex = asSocketException(ioe);
435 } finally {
436 endWrite(n > 0);
437 }
438 if (ex != null) {
439 throw ex;
440 }
441 return n;
442 }
443
498 {
499 synchronized (stateLock) {
500 int state = this.state;
501 if (state != ST_UNCONNECTED) {
502 if (state == ST_NEW)
503 throw new SocketException("Not created");
504 if (state == ST_CONNECTING)
505 throw new SocketException("Connection in progress");
506 if (state == ST_CONNECTED)
507 throw new SocketException("Already connected");
508 if (state >= ST_CLOSING)
509 throw new SocketException("Socket closed");
510 assert false;
511 }
512 this.state = ST_CONNECTING;
513
514 // save the remote address/port
515 this.address = address;
516 this.port = port;
517
518 readerThread = NativeThread.current();
519 return fd;
520 }
521 }
522
523 /**
524 * Marks the end of a connect operation that may have blocked.
525 * @throws SocketException is the socket is closed
526 */
527 private void endConnect(FileDescriptor fd, boolean completed) throws IOException {
528 synchronized (stateLock) {
529 readerThread = 0;
530 int state = this.state;
531 if (state == ST_CLOSING)
532 tryFinishClose();
533 if (completed && state == ST_CONNECTING) {
534 this.state = ST_CONNECTED;
535 localport = Net.localAddress(fd).getPort();
536 } else if (!completed && state >= ST_CLOSING) {
537 throw new SocketException("Socket closed");
538 }
539 }
540 }
541
542 /**
543 * Waits for a connection attempt to finish with a timeout
544 * @throws SocketTimeoutException if the connect timeout elapses
545 */
546 private boolean timedFinishConnect(FileDescriptor fd, long nanos) throws IOException {
547 long startNanos = System.nanoTime();
548 boolean polled = Net.pollConnectNow(fd);
549 while (!polled && isOpen()) {
653
654 @Override
655 protected void listen(int backlog) throws IOException {
656 synchronized (stateLock) {
657 ensureOpen();
658 if (localport == 0)
659 throw new SocketException("Not bound");
660 Net.listen(fd, backlog < 1 ? 50 : backlog);
661 }
662 }
663
664 /**
665 * Marks the beginning of an accept operation that might block.
666 * @throws SocketException if the socket is closed
667 */
668 private FileDescriptor beginAccept() throws SocketException {
669 synchronized (stateLock) {
670 ensureOpen();
671 if (localport == 0)
672 throw new SocketException("Not bound");
673 readerThread = NativeThread.current();
674 return fd;
675 }
676 }
677
678 /**
679 * Marks the end of an accept operation that may have blocked.
680 * @throws SocketException is the socket is closed
681 */
682 private void endAccept(boolean completed) throws SocketException {
683 synchronized (stateLock) {
684 int state = this.state;
685 readerThread = 0;
686 if (state == ST_CLOSING)
687 tryFinishClose();
688 if (!completed && state >= ST_CLOSING)
689 throw new SocketException("Socket closed");
690 }
691 }
692
693 /**
694 * Accepts a new connection with a timeout.
695 * @throws SocketTimeoutException if the accept timeout elapses
696 */
697 private int timedAccept(FileDescriptor fd,
698 FileDescriptor newfd,
699 InetSocketAddress[] isaa,
700 long nanos)
701 throws IOException
702 {
703 long startNanos = System.nanoTime();
704 int n = Net.accept(fd, newfd, isaa);
705 while (n == IOStatus.UNAVAILABLE && isOpen()) {
831 };
832 }
833
834 @Override
835 protected int available() throws IOException {
836 synchronized (stateLock) {
837 ensureOpenAndConnected();
838 if (isInputClosed) {
839 return 0;
840 } else {
841 return Net.available(fd);
842 }
843 }
844 }
845
846 /**
847 * Closes the socket if there are no I/O operations in progress.
848 */
849 private boolean tryClose() throws IOException {
850 assert Thread.holdsLock(stateLock) && state == ST_CLOSING;
851 if (readerThread == 0 && writerThread == 0) {
852 try {
853 cleaner.clean();
854 } catch (UncheckedIOException ioe) {
855 throw ioe.getCause();
856 } finally {
857 state = ST_CLOSED;
858 }
859 return true;
860 } else {
861 return false;
862 }
863 }
864
865 /**
866 * Invokes tryClose to attempt to close the socket.
867 *
868 * This method is used for deferred closing by I/O operations.
869 */
870 private void tryFinishClose() {
871 try {
1130 if (!Net.isReusePortAvailable())
1131 throw new SocketException("SO_REUSEPORT not supported");
1132 return Net.getSocketOption(fd, StandardSocketOptions.SO_REUSEPORT);
1133 default:
1134 throw new SocketException("Unknown option " + opt);
1135 }
1136 } catch (SocketException e) {
1137 throw e;
1138 } catch (IllegalArgumentException | IOException e) {
1139 throw asSocketException(e);
1140 }
1141 }
1142 }
1143
1144 @Override
1145 protected void shutdownInput() throws IOException {
1146 synchronized (stateLock) {
1147 ensureOpenAndConnected();
1148 if (!isInputClosed) {
1149 Net.shutdown(fd, Net.SHUT_RD);
1150 if (NativeThread.isVirtualThread(readerThread)) {
1151 Poller.stopPoll(fdVal(fd), Net.POLLIN);
1152 }
1153 isInputClosed = true;
1154 }
1155 }
1156 }
1157
1158 @Override
1159 protected void shutdownOutput() throws IOException {
1160 synchronized (stateLock) {
1161 ensureOpenAndConnected();
1162 if (!isOutputClosed) {
1163 Net.shutdown(fd, Net.SHUT_WR);
1164 if (NativeThread.isVirtualThread(writerThread)) {
1165 Poller.stopPoll(fdVal(fd), Net.POLLOUT);
1166 }
1167 isOutputClosed = true;
1168 }
1169 }
1170 }
1171
1172 @Override
1173 protected boolean supportsUrgentData() {
1174 return true;
1175 }
1176
1177 @Override
1178 protected void sendUrgentData(int data) throws IOException {
1179 writeLock.lock();
1180 try {
1181 int n = 0;
1182 FileDescriptor fd = beginWrite();
1183 try {
1184 configureNonBlockingIfNeeded(fd, false);
1185 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);
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 SocketException ex = null;
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 } catch (InterruptedIOException e) {
319 throw e;
320 } catch (ConnectionResetException e) {
321 connectionReset = true;
322 throw new SocketException("Connection reset");
323 } catch (IOException ioe) {
324 // translate to SocketException to maintain compatibility
325 ex = asSocketException(ioe);
364 return -1;
365 // read up to MAX_BUFFER_SIZE bytes
366 int size = Math.min(len, MAX_BUFFER_SIZE);
367 int n = implRead(b, off, size, remainingNanos);
368 if (n == -1)
369 readEOF = true;
370 return n;
371 } finally {
372 readLock.unlock();
373 }
374 }
375 }
376
377 /**
378 * Marks the beginning of a write operation that might block.
379 * @throws SocketException if the socket is closed or not connected
380 */
381 private FileDescriptor beginWrite() throws SocketException {
382 synchronized (stateLock) {
383 ensureOpenAndConnected();
384 writerThread = NativeThread.threadToSignal();
385 return fd;
386 }
387 }
388
389 /**
390 * Marks the end of a write operation that may have blocked.
391 * @throws SocketException is the socket is closed
392 */
393 private void endWrite(boolean completed) throws SocketException {
394 synchronized (stateLock) {
395 writerThread = null;
396 int state = this.state;
397 if (state == ST_CLOSING)
398 tryFinishClose();
399 if (!completed && state >= ST_CLOSING)
400 throw new SocketException("Socket closed");
401 }
402 }
403
404 /**
405 * Attempts to write a sequence of bytes to the socket from the given
406 * byte array.
407 */
408 private int tryWrite(FileDescriptor fd, byte[] b, int off, int len)
409 throws IOException
410 {
411 ByteBuffer src = Util.getTemporaryDirectBuffer(len);
412 assert src.position() == 0;
413 try {
414 src.put(b, off, len);
415 return nd.write(fd, ((DirectBuffer)src).address(), len);
416 } finally {
417 Util.offerFirstTemporaryDirectBuffer(src);
418 }
419 }
420
421 /**
422 * Writes a sequence of bytes to the socket from the given byte array.
423 * @return the number of bytes written
424 * @throws SocketException if the socket is closed or a socket I/O error occurs
425 */
426 private int implWrite(byte[] b, int off, int len) throws IOException {
427 int n = 0;
428 SocketException ex = null;
429 FileDescriptor fd = beginWrite();
430 try {
431
432 // experimental
433 if (Poller.supportWriteOps() && Thread.currentThread().isVirtual()) {
434 n = Poller.write(fdVal(fd), b, off, len, this::isOpen);
435 if (n != IOStatus.UNAVAILABLE) return n;
436 }
437
438 configureNonBlockingIfNeeded(fd, false);
439 n = tryWrite(fd, b, off, len);
440 while (IOStatus.okayToRetry(n) && isOpen()) {
441 park(fd, Net.POLLOUT);
442 n = tryWrite(fd, b, off, len);
443 }
444 } catch (InterruptedIOException e) {
445 throw e;
446 } catch (IOException ioe) {
447 // translate to SocketException to maintain compatibility
448 ex = asSocketException(ioe);
449 } finally {
450 endWrite(n > 0);
451 }
452 if (ex != null) {
453 throw ex;
454 }
455 return n;
456 }
457
512 {
513 synchronized (stateLock) {
514 int state = this.state;
515 if (state != ST_UNCONNECTED) {
516 if (state == ST_NEW)
517 throw new SocketException("Not created");
518 if (state == ST_CONNECTING)
519 throw new SocketException("Connection in progress");
520 if (state == ST_CONNECTED)
521 throw new SocketException("Already connected");
522 if (state >= ST_CLOSING)
523 throw new SocketException("Socket closed");
524 assert false;
525 }
526 this.state = ST_CONNECTING;
527
528 // save the remote address/port
529 this.address = address;
530 this.port = port;
531
532 readerThread = NativeThread.threadToSignal();
533 return fd;
534 }
535 }
536
537 /**
538 * Marks the end of a connect operation that may have blocked.
539 * @throws SocketException is the socket is closed
540 */
541 private void endConnect(FileDescriptor fd, boolean completed) throws IOException {
542 synchronized (stateLock) {
543 readerThread = null;
544 int state = this.state;
545 if (state == ST_CLOSING)
546 tryFinishClose();
547 if (completed && state == ST_CONNECTING) {
548 this.state = ST_CONNECTED;
549 localport = Net.localAddress(fd).getPort();
550 } else if (!completed && state >= ST_CLOSING) {
551 throw new SocketException("Socket closed");
552 }
553 }
554 }
555
556 /**
557 * Waits for a connection attempt to finish with a timeout
558 * @throws SocketTimeoutException if the connect timeout elapses
559 */
560 private boolean timedFinishConnect(FileDescriptor fd, long nanos) throws IOException {
561 long startNanos = System.nanoTime();
562 boolean polled = Net.pollConnectNow(fd);
563 while (!polled && isOpen()) {
667
668 @Override
669 protected void listen(int backlog) throws IOException {
670 synchronized (stateLock) {
671 ensureOpen();
672 if (localport == 0)
673 throw new SocketException("Not bound");
674 Net.listen(fd, backlog < 1 ? 50 : backlog);
675 }
676 }
677
678 /**
679 * Marks the beginning of an accept operation that might block.
680 * @throws SocketException if the socket is closed
681 */
682 private FileDescriptor beginAccept() throws SocketException {
683 synchronized (stateLock) {
684 ensureOpen();
685 if (localport == 0)
686 throw new SocketException("Not bound");
687 readerThread = NativeThread.threadToSignal();
688 return fd;
689 }
690 }
691
692 /**
693 * Marks the end of an accept operation that may have blocked.
694 * @throws SocketException is the socket is closed
695 */
696 private void endAccept(boolean completed) throws SocketException {
697 synchronized (stateLock) {
698 int state = this.state;
699 readerThread = null;
700 if (state == ST_CLOSING)
701 tryFinishClose();
702 if (!completed && state >= ST_CLOSING)
703 throw new SocketException("Socket closed");
704 }
705 }
706
707 /**
708 * Accepts a new connection with a timeout.
709 * @throws SocketTimeoutException if the accept timeout elapses
710 */
711 private int timedAccept(FileDescriptor fd,
712 FileDescriptor newfd,
713 InetSocketAddress[] isaa,
714 long nanos)
715 throws IOException
716 {
717 long startNanos = System.nanoTime();
718 int n = Net.accept(fd, newfd, isaa);
719 while (n == IOStatus.UNAVAILABLE && isOpen()) {
845 };
846 }
847
848 @Override
849 protected int available() throws IOException {
850 synchronized (stateLock) {
851 ensureOpenAndConnected();
852 if (isInputClosed) {
853 return 0;
854 } else {
855 return Net.available(fd);
856 }
857 }
858 }
859
860 /**
861 * Closes the socket if there are no I/O operations in progress.
862 */
863 private boolean tryClose() throws IOException {
864 assert Thread.holdsLock(stateLock) && state == ST_CLOSING;
865 if (readerThread == null && writerThread == null) {
866 try {
867 cleaner.clean();
868 } catch (UncheckedIOException ioe) {
869 throw ioe.getCause();
870 } finally {
871 state = ST_CLOSED;
872 }
873 return true;
874 } else {
875 return false;
876 }
877 }
878
879 /**
880 * Invokes tryClose to attempt to close the socket.
881 *
882 * This method is used for deferred closing by I/O operations.
883 */
884 private void tryFinishClose() {
885 try {
1144 if (!Net.isReusePortAvailable())
1145 throw new SocketException("SO_REUSEPORT not supported");
1146 return Net.getSocketOption(fd, StandardSocketOptions.SO_REUSEPORT);
1147 default:
1148 throw new SocketException("Unknown option " + opt);
1149 }
1150 } catch (SocketException e) {
1151 throw e;
1152 } catch (IllegalArgumentException | IOException e) {
1153 throw asSocketException(e);
1154 }
1155 }
1156 }
1157
1158 @Override
1159 protected void shutdownInput() throws IOException {
1160 synchronized (stateLock) {
1161 ensureOpenAndConnected();
1162 if (!isInputClosed) {
1163 Net.shutdown(fd, Net.SHUT_RD);
1164 if (readerThread != null && readerThread.isVirtual()) {
1165 Poller.stopPoll(readerThread);
1166 }
1167 isInputClosed = true;
1168 }
1169 }
1170 }
1171
1172 @Override
1173 protected void shutdownOutput() throws IOException {
1174 synchronized (stateLock) {
1175 ensureOpenAndConnected();
1176 if (!isOutputClosed) {
1177 Net.shutdown(fd, Net.SHUT_WR);
1178 if (writerThread != null && writerThread.isVirtual()) {
1179 Poller.stopPoll(writerThread);
1180 }
1181 isOutputClosed = true;
1182 }
1183 }
1184 }
1185
1186 @Override
1187 protected boolean supportsUrgentData() {
1188 return true;
1189 }
1190
1191 @Override
1192 protected void sendUrgentData(int data) throws IOException {
1193 writeLock.lock();
1194 try {
1195 int n = 0;
1196 FileDescriptor fd = beginWrite();
1197 try {
1198 configureNonBlockingIfNeeded(fd, false);
1199 do {
|