1 /* |
1 /* |
2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
246 Util.offerFirstTemporaryDirectBuffer(dst); |
246 Util.offerFirstTemporaryDirectBuffer(dst); |
247 } |
247 } |
248 } |
248 } |
249 |
249 |
250 /** |
250 /** |
|
251 * Reads bytes from the socket into the given byte array with a timeout. |
|
252 * @throws SocketTimeoutException if the read timeout elapses |
|
253 */ |
|
254 private int timedRead(FileDescriptor fd, byte[] b, int off, int len, int millis) |
|
255 throws IOException |
|
256 { |
|
257 long nanos = NANOSECONDS.convert(millis, TimeUnit.MILLISECONDS); |
|
258 long remainingNanos = nanos; |
|
259 long startNanos = System.nanoTime(); |
|
260 int n; |
|
261 do { |
|
262 park(fd, Net.POLLIN, remainingNanos); |
|
263 n = tryRead(fd, b, off, len); |
|
264 if (n == IOStatus.UNAVAILABLE) { |
|
265 remainingNanos = nanos - (System.nanoTime() - startNanos); |
|
266 if (remainingNanos <= 0) { |
|
267 throw new SocketTimeoutException("Read timed out"); |
|
268 } |
|
269 } |
|
270 } while (n == IOStatus.UNAVAILABLE && isOpen()); |
|
271 return n; |
|
272 } |
|
273 |
|
274 /** |
251 * Reads bytes from the socket into the given byte array. |
275 * Reads bytes from the socket into the given byte array. |
252 * @return the number of bytes read |
276 * @return the number of bytes read |
253 * @throws IOException if the socket is closed or an I/O occurs |
277 * @throws IOException if the socket is closed or an I/O occurs |
254 * @throws SocketTimeoutException if the read timeout elapses |
278 * @throws SocketTimeoutException if the read timeout elapses |
255 */ |
279 */ |
256 private int read(byte[] b, int off, int len) throws IOException { |
280 private int read(byte[] b, int off, int len) throws IOException { |
257 readLock.lock(); |
281 readLock.lock(); |
258 try { |
282 try { |
259 int timeout = this.timeout; |
|
260 int n = 0; |
283 int n = 0; |
261 FileDescriptor fd = beginRead(); |
284 FileDescriptor fd = beginRead(); |
262 try { |
285 try { |
263 if (isInputClosed) |
286 if (isInputClosed) |
264 return IOStatus.EOF; |
287 return IOStatus.EOF; |
|
288 int timeout = this.timeout; |
265 configureNonBlockingIfNeeded(fd, timeout); |
289 configureNonBlockingIfNeeded(fd, timeout); |
266 n = tryRead(fd, b, off, len); |
290 n = tryRead(fd, b, off, len); |
267 if (IOStatus.okayToRetry(n) && isOpen()) { |
291 if (IOStatus.okayToRetry(n) && isOpen()) { |
268 if (timeout > 0) { |
292 if (timeout > 0) { |
269 // read with timeout |
293 // read with timeout |
270 long nanos = NANOSECONDS.convert(timeout, TimeUnit.MILLISECONDS); |
294 n = timedRead(fd, b, off, len, timeout); |
271 do { |
|
272 long startTime = System.nanoTime(); |
|
273 park(fd, Net.POLLIN, nanos); |
|
274 n = tryRead(fd, b, off, len); |
|
275 if (n == IOStatus.UNAVAILABLE) { |
|
276 nanos -= System.nanoTime() - startTime; |
|
277 if (nanos <= 0) |
|
278 throw new SocketTimeoutException("Read timed out"); |
|
279 } |
|
280 } while (n == IOStatus.UNAVAILABLE && isOpen()); |
|
281 } else { |
295 } else { |
282 // read, no timeout |
296 // read, no timeout |
283 do { |
297 do { |
284 park(fd, Net.POLLIN); |
298 park(fd, Net.POLLIN); |
285 n = tryRead(fd, b, off, len); |
299 n = tryRead(fd, b, off, len); |
521 localport = Net.localAddress(fd).getPort(); |
535 localport = Net.localAddress(fd).getPort(); |
522 } else if (!completed && state >= ST_CLOSING) { |
536 } else if (!completed && state >= ST_CLOSING) { |
523 throw new SocketException("Socket closed"); |
537 throw new SocketException("Socket closed"); |
524 } |
538 } |
525 } |
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 int timedFinishConnect(FileDescriptor fd, int millis) throws IOException { |
|
547 long nanos = NANOSECONDS.convert(millis, TimeUnit.MILLISECONDS); |
|
548 long remainingNanos = nanos; |
|
549 long startNanos = System.nanoTime(); |
|
550 int n; |
|
551 do { |
|
552 park(fd, Net.POLLOUT, remainingNanos); |
|
553 n = Net.pollConnectNow(fd); |
|
554 if (n == 0) { |
|
555 remainingNanos = nanos - (System.nanoTime() - startNanos); |
|
556 if (remainingNanos <= 0) { |
|
557 throw new SocketTimeoutException("Connect timed out"); |
|
558 } |
|
559 } |
|
560 } while (n == 0 && isOpen()); |
|
561 return n; |
526 } |
562 } |
527 |
563 |
528 /** |
564 /** |
529 * Connect the socket. Closes the socket if connection cannot be established. |
565 * Connect the socket. Closes the socket if connection cannot be established. |
530 * @throws IllegalArgumentException if the address is not an InetSocketAddress |
566 * @throws IllegalArgumentException if the address is not an InetSocketAddress |
553 try { |
589 try { |
554 configureNonBlockingIfNeeded(fd, millis); |
590 configureNonBlockingIfNeeded(fd, millis); |
555 int n = Net.connect(fd, address, port); |
591 int n = Net.connect(fd, address, port); |
556 if (IOStatus.okayToRetry(n) && isOpen()) { |
592 if (IOStatus.okayToRetry(n) && isOpen()) { |
557 if (millis > 0) { |
593 if (millis > 0) { |
558 // connect with timeout |
594 // finish connect with timeout |
559 assert nonBlocking; |
595 n = timedFinishConnect(fd, millis); |
560 long nanos = NANOSECONDS.convert(millis, MILLISECONDS); |
|
561 do { |
|
562 long startTime = System.nanoTime(); |
|
563 park(fd, Net.POLLOUT, nanos); |
|
564 n = Net.pollConnectNow(fd); |
|
565 if (n == 0) { |
|
566 nanos -= System.nanoTime() - startTime; |
|
567 if (nanos <= 0) |
|
568 throw new SocketTimeoutException("Connect timed out"); |
|
569 } |
|
570 } while (n == 0 && isOpen()); |
|
571 } else { |
596 } else { |
572 // connect, no timeout |
597 // finish connect, no timeout |
573 do { |
598 do { |
574 park(fd, Net.POLLOUT); |
599 park(fd, Net.POLLOUT); |
575 n = Net.pollConnectNow(fd); |
600 n = Net.pollConnectNow(fd); |
576 } while (n == 0 && isOpen()); |
601 } while (n == 0 && isOpen()); |
577 } |
602 } |
657 if (state == ST_CLOSING) |
682 if (state == ST_CLOSING) |
658 stateLock.notifyAll(); |
683 stateLock.notifyAll(); |
659 if (!completed && state >= ST_CLOSING) |
684 if (!completed && state >= ST_CLOSING) |
660 throw new SocketException("Socket closed"); |
685 throw new SocketException("Socket closed"); |
661 } |
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 int millis) |
|
697 throws IOException |
|
698 { |
|
699 long nanos = NANOSECONDS.convert(millis, TimeUnit.MILLISECONDS); |
|
700 long remainingNanos = nanos; |
|
701 long startNanos = System.nanoTime(); |
|
702 int n; |
|
703 do { |
|
704 park(fd, Net.POLLIN, remainingNanos); |
|
705 n = ServerSocketChannelImpl.accept0(fd, newfd, isaa); |
|
706 if (n == IOStatus.UNAVAILABLE) { |
|
707 remainingNanos = nanos - (System.nanoTime() - startNanos); |
|
708 if (remainingNanos <= 0) { |
|
709 throw new SocketTimeoutException("Accept timed out"); |
|
710 } |
|
711 } |
|
712 } while (n == IOStatus.UNAVAILABLE && isOpen()); |
|
713 return n; |
662 } |
714 } |
663 |
715 |
664 @Override |
716 @Override |
665 protected void accept(SocketImpl si) throws IOException { |
717 protected void accept(SocketImpl si) throws IOException { |
666 // accept a connection |
718 // accept a connection |
677 configureNonBlockingIfNeeded(fd, timeout); |
729 configureNonBlockingIfNeeded(fd, timeout); |
678 n = ServerSocketChannelImpl.accept0(fd, newfd, isaa); |
730 n = ServerSocketChannelImpl.accept0(fd, newfd, isaa); |
679 if (IOStatus.okayToRetry(n) && isOpen()) { |
731 if (IOStatus.okayToRetry(n) && isOpen()) { |
680 if (timeout > 0) { |
732 if (timeout > 0) { |
681 // accept with timeout |
733 // accept with timeout |
682 assert nonBlocking; |
734 n = timedAccept(fd, newfd, isaa, timeout); |
683 long nanos = NANOSECONDS.convert(timeout, TimeUnit.MILLISECONDS); |
|
684 do { |
|
685 long startTime = System.nanoTime(); |
|
686 park(fd, Net.POLLIN, nanos); |
|
687 n = ServerSocketChannelImpl.accept0(fd, newfd, isaa); |
|
688 if (n == IOStatus.UNAVAILABLE) { |
|
689 nanos -= System.nanoTime() - startTime; |
|
690 if (nanos <= 0) |
|
691 throw new SocketTimeoutException("Accept timed out"); |
|
692 } |
|
693 } while (n == IOStatus.UNAVAILABLE && isOpen()); |
|
694 } else { |
735 } else { |
695 // accept, no timeout |
736 // accept, no timeout |
696 do { |
737 do { |
697 park(fd, Net.POLLIN); |
738 park(fd, Net.POLLIN); |
698 n = ServerSocketChannelImpl.accept0(fd, newfd, isaa); |
739 n = ServerSocketChannelImpl.accept0(fd, newfd, isaa); |