523 |
523 |
524 /** |
524 /** |
525 * Waits for a connection attempt to finish with a timeout. |
525 * Waits for a connection attempt to finish with a timeout. |
526 * @throws SocketTimeoutException if the connect timeout elapses |
526 * @throws SocketTimeoutException if the connect timeout elapses |
527 */ |
527 */ |
528 private int timedFinishConnect(FileDescriptor fd, int millis) throws IOException { |
528 private boolean timedFinishConnect(FileDescriptor fd, int millis) throws IOException { |
529 long nanos = NANOSECONDS.convert(millis, TimeUnit.MILLISECONDS); |
529 long nanos = NANOSECONDS.convert(millis, TimeUnit.MILLISECONDS); |
530 long remainingNanos = nanos; |
530 long remainingNanos = nanos; |
531 long startNanos = System.nanoTime(); |
531 long startNanos = System.nanoTime(); |
532 int n; |
532 boolean connected; |
533 do { |
533 do { |
534 park(fd, Net.POLLOUT, remainingNanos); |
534 park(fd, Net.POLLOUT, remainingNanos); |
535 n = Net.pollConnectNow(fd); |
535 connected = Net.pollConnectNow(fd); |
536 if (n == 0) { |
536 if (!connected) { |
537 remainingNanos = nanos - (System.nanoTime() - startNanos); |
537 remainingNanos = nanos - (System.nanoTime() - startNanos); |
538 if (remainingNanos <= 0) { |
538 if (remainingNanos <= 0) { |
539 throw new SocketTimeoutException("Connect timed out"); |
539 throw new SocketTimeoutException("Connect timed out"); |
540 } |
540 } |
541 } |
541 } |
542 } while (n == 0 && isOpen()); |
542 } while (!connected && isOpen()); |
543 return n; |
543 return connected; |
544 } |
544 } |
545 |
545 |
546 /** |
546 /** |
547 * Attempts to establish a connection to the given socket address with a |
547 * Attempts to establish a connection to the given socket address with a |
548 * timeout. Closes the socket if connection cannot be established. |
548 * timeout. Closes the socket if connection cannot be established. |
570 boolean connected = false; |
570 boolean connected = false; |
571 FileDescriptor fd = beginConnect(address, port); |
571 FileDescriptor fd = beginConnect(address, port); |
572 try { |
572 try { |
573 configureNonBlockingIfNeeded(fd, millis); |
573 configureNonBlockingIfNeeded(fd, millis); |
574 int n = Net.connect(fd, address, port); |
574 int n = Net.connect(fd, address, port); |
575 if (IOStatus.okayToRetry(n) && isOpen()) { |
575 if (n > 0 && isOpen()) { |
|
576 connected = true; |
|
577 } else if (IOStatus.okayToRetry(n) && isOpen()) { |
576 if (millis > 0) { |
578 if (millis > 0) { |
577 // finish connect with timeout |
579 // finish connect with timeout |
578 n = timedFinishConnect(fd, millis); |
580 connected = timedFinishConnect(fd, millis); |
579 } else { |
581 } else { |
580 // finish connect, no timeout |
582 // finish connect, no timeout |
581 do { |
583 do { |
582 park(fd, Net.POLLOUT); |
584 park(fd, Net.POLLOUT); |
583 n = Net.pollConnectNow(fd); |
585 connected = Net.pollConnectNow(fd); |
584 } while (n == 0 && isOpen()); |
586 } while (!connected && isOpen()); |
585 } |
587 } |
586 } |
588 } |
587 connected = (n > 0) && isOpen(); |
|
588 } finally { |
589 } finally { |
589 endConnect(connected); |
590 endConnect(connected); |
590 } |
591 } |
591 } finally { |
592 } finally { |
592 connectLock.unlock(); |
593 connectLock.unlock(); |
811 }; |
812 }; |
812 } |
813 } |
813 |
814 |
814 @Override |
815 @Override |
815 protected int available() throws IOException { |
816 protected int available() throws IOException { |
816 readLock.lock(); |
817 synchronized (stateLock) { |
817 try { |
|
818 ensureOpenAndConnected(); |
818 ensureOpenAndConnected(); |
819 if (isInputClosed) { |
819 if (isInputClosed) { |
820 return 0; |
820 return 0; |
821 } else { |
821 } else { |
822 return Net.available(fd); |
822 return Net.available(fd); |
823 } |
823 } |
824 } finally { |
|
825 readLock.unlock(); |
|
826 } |
824 } |
827 } |
825 } |
828 |
826 |
829 /** |
827 /** |
830 * Closes the socket, signalling and waiting for blocking I/O operations |
828 * Closes the socket, signalling and waiting for blocking I/O operations |