172 private void park(FileDescriptor fd, int event, long nanos) throws IOException { |
172 private void park(FileDescriptor fd, int event, long nanos) throws IOException { |
173 long millis; |
173 long millis; |
174 if (nanos == 0) { |
174 if (nanos == 0) { |
175 millis = -1; |
175 millis = -1; |
176 } else { |
176 } else { |
177 millis = MILLISECONDS.convert(nanos, NANOSECONDS); |
177 millis = NANOSECONDS.toMillis(nanos); |
178 } |
178 } |
179 Net.poll(fd, event, millis); |
179 Net.poll(fd, event, millis); |
180 } |
180 } |
181 |
181 |
182 /** |
182 /** |
264 */ |
264 */ |
265 private int timedRead(FileDescriptor fd, byte[] b, int off, int len, long nanos) |
265 private int timedRead(FileDescriptor fd, byte[] b, int off, int len, long nanos) |
266 throws IOException |
266 throws IOException |
267 { |
267 { |
268 assert nonBlocking; |
268 assert nonBlocking; |
269 long remainingNanos = nanos; |
|
270 long startNanos = System.nanoTime(); |
269 long startNanos = System.nanoTime(); |
271 int n; |
270 int n = tryRead(fd, b, off, len); |
272 do { |
271 while (n == IOStatus.UNAVAILABLE && isOpen()) { |
|
272 long remainingNanos = nanos - (System.nanoTime() - startNanos); |
|
273 if (remainingNanos <= 0) { |
|
274 throw new SocketTimeoutException("Read timed out"); |
|
275 } |
273 park(fd, Net.POLLIN, remainingNanos); |
276 park(fd, Net.POLLIN, remainingNanos); |
274 n = tryRead(fd, b, off, len); |
277 n = tryRead(fd, b, off, len); |
275 if (n == IOStatus.UNAVAILABLE) { |
278 } |
276 remainingNanos = nanos - (System.nanoTime() - startNanos); |
|
277 if (remainingNanos <= 0) { |
|
278 throw new SocketTimeoutException("Read timed out"); |
|
279 } |
|
280 } |
|
281 } while (n == IOStatus.UNAVAILABLE && isOpen()); |
|
282 return n; |
279 return n; |
283 } |
280 } |
284 |
281 |
285 /** |
282 /** |
286 * Reads bytes from the socket into the given byte array. |
283 * Reads bytes from the socket into the given byte array. |
295 if (connectionReset) |
292 if (connectionReset) |
296 throw new SocketException("Connection reset"); |
293 throw new SocketException("Connection reset"); |
297 if (isInputClosed) |
294 if (isInputClosed) |
298 return -1; |
295 return -1; |
299 int timeout = this.timeout; |
296 int timeout = this.timeout; |
300 if (timeout > 0) |
297 if (timeout > 0) { |
|
298 // read with timeout |
301 configureNonBlocking(fd); |
299 configureNonBlocking(fd); |
302 n = tryRead(fd, b, off, len); |
300 n = timedRead(fd, b, off, len, MILLISECONDS.toNanos(timeout)); |
303 if (IOStatus.okayToRetry(n) && isOpen()) { |
301 } else { |
304 if (timeout > 0) { |
302 // read, no timeout |
305 // read with timeout |
303 n = tryRead(fd, b, off, len); |
306 long nanos = NANOSECONDS.convert(timeout, MILLISECONDS); |
304 while (IOStatus.okayToRetry(n) && isOpen()) { |
307 n = timedRead(fd, b, off, len, nanos); |
305 park(fd, Net.POLLIN); |
308 } else { |
306 n = tryRead(fd, b, off, len); |
309 // read, no timeout |
|
310 do { |
|
311 park(fd, Net.POLLIN); |
|
312 n = tryRead(fd, b, off, len); |
|
313 } while (IOStatus.okayToRetry(n) && isOpen()); |
|
314 } |
307 } |
315 } |
308 } |
316 return n; |
309 return n; |
317 } catch (SocketTimeoutException e) { |
310 } catch (SocketTimeoutException e) { |
318 throw e; |
311 throw e; |
547 |
540 |
548 /** |
541 /** |
549 * Waits for a connection attempt to finish with a timeout |
542 * Waits for a connection attempt to finish with a timeout |
550 * @throws SocketTimeoutException if the connect timeout elapses |
543 * @throws SocketTimeoutException if the connect timeout elapses |
551 */ |
544 */ |
552 private void timedFinishConnect(FileDescriptor fd, long nanos) throws IOException { |
545 private boolean timedFinishConnect(FileDescriptor fd, long nanos) throws IOException { |
553 long remainingNanos = nanos; |
|
554 long startNanos = System.nanoTime(); |
546 long startNanos = System.nanoTime(); |
555 boolean polled; |
547 boolean polled = Net.pollConnectNow(fd); |
556 do { |
548 while (!polled && isOpen()) { |
|
549 long remainingNanos = nanos - (System.nanoTime() - startNanos); |
|
550 if (remainingNanos <= 0) { |
|
551 throw new SocketTimeoutException("Connect timed out"); |
|
552 } |
557 park(fd, Net.POLLOUT, remainingNanos); |
553 park(fd, Net.POLLOUT, remainingNanos); |
558 polled = Net.pollConnectNow(fd); |
554 polled = Net.pollConnectNow(fd); |
559 if (!polled) { |
555 } |
560 remainingNanos = nanos - (System.nanoTime() - startNanos); |
556 return polled && isOpen(); |
561 if (remainingNanos <= 0) { |
|
562 throw new SocketTimeoutException("Connect timed out"); |
|
563 } |
|
564 } |
|
565 } while (!polled && isOpen()); |
|
566 } |
557 } |
567 |
558 |
568 /** |
559 /** |
569 * Attempts to establish a connection to the given socket address with a |
560 * Attempts to establish a connection to the given socket address with a |
570 * timeout. Closes the socket if connection cannot be established. |
561 * timeout. Closes the socket if connection cannot be established. |
594 FileDescriptor fd = beginConnect(address, port); |
585 FileDescriptor fd = beginConnect(address, port); |
595 try { |
586 try { |
596 if (millis > 0) |
587 if (millis > 0) |
597 configureNonBlocking(fd); |
588 configureNonBlocking(fd); |
598 int n = Net.connect(fd, address, port); |
589 int n = Net.connect(fd, address, port); |
599 if (isOpen()) { |
590 if (n > 0) { |
600 if (n > 0) { |
591 // connection established |
601 // connection established |
592 connected = true; |
602 connected = true; |
593 } else { |
603 } else if (IOStatus.okayToRetry(n)) { |
594 assert IOStatus.okayToRetry(n); |
604 // not established or interrupted |
595 if (millis > 0) { |
605 if (millis > 0) { |
596 // finish connect with timeout |
606 // finish connect with timeout |
597 long nanos = MILLISECONDS.toNanos(millis); |
607 long nanos = NANOSECONDS.convert(millis, MILLISECONDS); |
598 connected = timedFinishConnect(fd, nanos); |
608 timedFinishConnect(fd, nanos); |
599 } else { |
609 } else { |
600 // finish connect, no timeout |
610 // finish connect, no timeout |
601 boolean polled = false; |
611 boolean polled; |
602 while (!polled && isOpen()) { |
612 do { |
603 park(fd, Net.POLLOUT); |
613 park(fd, Net.POLLOUT); |
604 polled = Net.pollConnectNow(fd); |
614 polled = Net.pollConnectNow(fd); |
|
615 } while (!polled && isOpen()); |
|
616 } |
605 } |
617 connected = isOpen(); |
606 connected = polled && isOpen(); |
618 } |
607 } |
619 } |
608 } |
620 } finally { |
609 } finally { |
621 endConnect(fd, connected); |
610 endConnect(fd, connected); |
622 } |
611 } |
717 InetSocketAddress[] isaa, |
706 InetSocketAddress[] isaa, |
718 long nanos) |
707 long nanos) |
719 throws IOException |
708 throws IOException |
720 { |
709 { |
721 assert nonBlocking; |
710 assert nonBlocking; |
722 long remainingNanos = nanos; |
|
723 long startNanos = System.nanoTime(); |
711 long startNanos = System.nanoTime(); |
724 int n; |
712 int n = Net.accept(fd, newfd, isaa); |
725 do { |
713 while (n == IOStatus.UNAVAILABLE && isOpen()) { |
|
714 long remainingNanos = nanos - (System.nanoTime() - startNanos); |
|
715 if (remainingNanos <= 0) { |
|
716 throw new SocketTimeoutException("Accept timed out"); |
|
717 } |
726 park(fd, Net.POLLIN, remainingNanos); |
718 park(fd, Net.POLLIN, remainingNanos); |
727 n = Net.accept(fd, newfd, isaa); |
719 n = Net.accept(fd, newfd, isaa); |
728 if (n == IOStatus.UNAVAILABLE) { |
720 } |
729 remainingNanos = nanos - (System.nanoTime() - startNanos); |
|
730 if (remainingNanos <= 0) { |
|
731 throw new SocketTimeoutException("Accept timed out"); |
|
732 } |
|
733 } |
|
734 } while (n == IOStatus.UNAVAILABLE && isOpen()); |
|
735 return n; |
721 return n; |
736 } |
722 } |
737 |
723 |
738 /** |
724 /** |
739 * Accepts a new connection so that the given SocketImpl is connected to |
725 * Accepts a new connection so that the given SocketImpl is connected to |
766 // accept a connection |
752 // accept a connection |
767 try { |
753 try { |
768 int n = 0; |
754 int n = 0; |
769 FileDescriptor fd = beginAccept(); |
755 FileDescriptor fd = beginAccept(); |
770 try { |
756 try { |
771 if (remainingNanos > 0) |
757 if (remainingNanos > 0) { |
|
758 // accept with timeout |
772 configureNonBlocking(fd); |
759 configureNonBlocking(fd); |
773 n = Net.accept(fd, newfd, isaa); |
760 n = timedAccept(fd, newfd, isaa, remainingNanos); |
774 if (IOStatus.okayToRetry(n) && isOpen()) { |
761 } else { |
775 if (remainingNanos > 0) { |
762 // accept, no timeout |
776 // accept with timeout |
763 n = Net.accept(fd, newfd, isaa); |
777 n = timedAccept(fd, newfd, isaa, remainingNanos); |
764 while (IOStatus.okayToRetry(n) && isOpen()) { |
778 } else { |
765 park(fd, Net.POLLIN); |
779 // accept, no timeout |
766 n = Net.accept(fd, newfd, isaa); |
780 do { |
|
781 park(fd, Net.POLLIN); |
|
782 n = Net.accept(fd, newfd, isaa); |
|
783 } while (IOStatus.okayToRetry(n) && isOpen()); |
|
784 } |
767 } |
785 } |
768 } |
786 } finally { |
769 } finally { |
787 endAccept(n > 0); |
770 endAccept(n > 0); |
788 assert IOStatus.check(n); |
771 assert IOStatus.check(n); |