436 if (debug) {
437 System.err.println("Writing request to: " + outStream);
438 }
439
440 try {
441 synchronized (this) {
442 outStream.write(ber.getBuf(), 0, ber.getDataLen());
443 outStream.flush();
444 }
445 } catch (IOException e) {
446 cleanup(null, true);
447 throw (closureReason = e); // rethrow
448 }
449
450 return req;
451 }
452
453 /**
454 * Reads a reply; waits until one is ready.
455 */
456 BerDecoder readReply(LdapRequest ldr)
457 throws IOException, NamingException {
458 BerDecoder rber;
459
460 // Track down elapsed time to workaround spurious wakeups
461 long elapsedMilli = 0;
462 long elapsedNano = 0;
463
464 while (((rber = ldr.getReplyBer()) == null) &&
465 (readTimeout <= 0 || elapsedMilli < readTimeout))
466 {
467 try {
468 // If socket closed, don't even try
469 synchronized (this) {
470 if (sock == null) {
471 throw new ServiceUnavailableException(host + ":" + port +
472 "; socket closed");
473 }
474 }
475 synchronized (ldr) {
476 // check if condition has changed since our last check
477 rber = ldr.getReplyBer();
478 if (rber == null) {
479 if (readTimeout > 0) { // Socket read timeout is specified
480 long beginNano = System.nanoTime();
481
482 // will be woken up before readTimeout if reply is
483 // available
484 ldr.wait(readTimeout - elapsedMilli);
485 elapsedNano += (System.nanoTime() - beginNano);
486 elapsedMilli += elapsedNano / 1000_000;
487 elapsedNano %= 1000_000;
488
489 } else {
490 // no timeout is set so we wait infinitely until
491 // a response is received
492 // https://docs.oracle.com/javase/8/docs/technotes/guides/jndi/jndi-ldap.html#PROP
493 ldr.wait();
494 }
495 } else {
496 break;
497 }
498 }
499 } catch (InterruptedException ex) {
500 throw new InterruptedNamingException(
501 "Interrupted during LDAP operation");
502 }
503 }
504
505 if ((rber == null) && (elapsedMilli >= readTimeout)) {
506 abandonRequest(ldr, null);
507 throw new NamingException("LDAP response read timed out, timeout used:"
508 + readTimeout + "ms." );
509
510 }
511 return rber;
512 }
513
514
515 ////////////////////////////////////////////////////////////////////////////
516 //
517 // Methods to add, find, delete, and abandon requests made to server
518 //
519 ////////////////////////////////////////////////////////////////////////////
520
521 private synchronized void addRequest(LdapRequest ldapRequest) {
522
523 LdapRequest ldr = pendingRequests;
524 if (ldr == null) {
525 pendingRequests = ldapRequest;
526 ldapRequest.next = null;
527 } else {
528 ldapRequest.next = pendingRequests;
529 pendingRequests = ldapRequest;
530 }
531 }
532
533 synchronized LdapRequest findRequest(int msgId) {
534
688 sock.close();
689 unpauseReader();
690 } catch (IOException ie) {
691 if (debug)
692 System.err.println("Connection: problem closing socket: " + ie);
693 }
694 if (!notifyParent) {
695 LdapRequest ldr = pendingRequests;
696 while (ldr != null) {
697 ldr.cancel();
698 ldr = ldr.next;
699 }
700 }
701 sock = null;
702 }
703 nparent = notifyParent;
704 }
705 if (nparent) {
706 LdapRequest ldr = pendingRequests;
707 while (ldr != null) {
708
709 synchronized (ldr) {
710 ldr.notify();
711 ldr = ldr.next;
712 }
713 }
714 }
715 }
716 if (nparent) {
717 parent.processConnectionClosure();
718 }
719 }
720
721
722 // Assume everything is "quiet"
723 // "synchronize" might lead to deadlock so don't synchronize method
724 // Use streamLock instead for synchronizing update to stream
725
726 synchronized public void replaceStreams(InputStream newIn, OutputStream newOut) {
727 if (debug) {
728 System.err.println("Replacing " + inStream + " with: " + newIn);
729 System.err.println("Replacing " + outStream + " with: " + newOut);
730 }
731
732 inStream = newIn;
733
734 // Cleanup old stream
735 try {
783 * plain ones and then closes the SSL socket.
784 * If the reader thread attempts to read, or was reading, from
785 * the SSL socket (that is, it got to the read BEFORE replaceStreams()),
786 * the SSL socket close will cause the reader thread to
787 * get an EOF/exception and reexamine the input stream.
788 * If the reader thread sees a new stream, it reattempts the read.
789 * If the underlying socket is still alive, then the new read will succeed.
790 * If the underlying socket has been closed also, then the new read will
791 * fail and the reader thread exits.
792 * If the reader thread attempts to read, or was reading, from the plain
793 * socket (that is, it got to the read AFTER replaceStreams()), the
794 * SSL socket close will have no effect on the reader thread.
795 *
796 * The check for new stream is made only
797 * in the first attempt at reading a BER buffer; the reader should
798 * never be in midst of reading a buffer when a nonfatal close occurs.
799 * If this occurs, then the connection is in an inconsistent state and
800 * the safest thing to do is to shut it down.
801 */
802
803 private Object pauseLock = new Object(); // lock for reader to wait on while paused
804 private boolean paused = false; // paused state of reader
805
806 /*
807 * Unpauses reader thread if it was paused
808 */
809 private void unpauseReader() throws IOException {
810 synchronized (pauseLock) {
811 if (paused) {
812 if (debug) {
813 System.err.println("Unpausing reader; read from: " +
814 inStream);
815 }
816 paused = false;
817 pauseLock.notify();
818 }
819 }
820 }
821
822 /*
823 * Pauses reader so that it stops reading from the input stream.
|
436 if (debug) {
437 System.err.println("Writing request to: " + outStream);
438 }
439
440 try {
441 synchronized (this) {
442 outStream.write(ber.getBuf(), 0, ber.getDataLen());
443 outStream.flush();
444 }
445 } catch (IOException e) {
446 cleanup(null, true);
447 throw (closureReason = e); // rethrow
448 }
449
450 return req;
451 }
452
453 /**
454 * Reads a reply; waits until one is ready.
455 */
456 BerDecoder readReply(LdapRequest ldr) throws IOException, NamingException {
457 BerDecoder rber;
458
459 try {
460 // if no timeout is set so we wait infinitely until
461 // a response is received
462 // http://docs.oracle.com/javase/8/docs/technotes/guides/jndi/jndi-ldap.html#PROP
463 rber = ldr.getReplyBer(readTimeout);
464 } catch (InterruptedException ex) {
465 throw new InterruptedNamingException(
466 "Interrupted during LDAP operation");
467 }
468
469 if (rber == null) {
470 abandonRequest(ldr, null);
471 throw new NamingException(
472 "LDAP response read timed out, timeout used:"
473 + readTimeout + "ms." );
474
475 }
476 return rber;
477 }
478
479 ////////////////////////////////////////////////////////////////////////////
480 //
481 // Methods to add, find, delete, and abandon requests made to server
482 //
483 ////////////////////////////////////////////////////////////////////////////
484
485 private synchronized void addRequest(LdapRequest ldapRequest) {
486
487 LdapRequest ldr = pendingRequests;
488 if (ldr == null) {
489 pendingRequests = ldapRequest;
490 ldapRequest.next = null;
491 } else {
492 ldapRequest.next = pendingRequests;
493 pendingRequests = ldapRequest;
494 }
495 }
496
497 synchronized LdapRequest findRequest(int msgId) {
498
652 sock.close();
653 unpauseReader();
654 } catch (IOException ie) {
655 if (debug)
656 System.err.println("Connection: problem closing socket: " + ie);
657 }
658 if (!notifyParent) {
659 LdapRequest ldr = pendingRequests;
660 while (ldr != null) {
661 ldr.cancel();
662 ldr = ldr.next;
663 }
664 }
665 sock = null;
666 }
667 nparent = notifyParent;
668 }
669 if (nparent) {
670 LdapRequest ldr = pendingRequests;
671 while (ldr != null) {
672 ldr.close();
673 ldr = ldr.next;
674 }
675 }
676 }
677 if (nparent) {
678 parent.processConnectionClosure();
679 }
680 }
681
682
683 // Assume everything is "quiet"
684 // "synchronize" might lead to deadlock so don't synchronize method
685 // Use streamLock instead for synchronizing update to stream
686
687 synchronized public void replaceStreams(InputStream newIn, OutputStream newOut) {
688 if (debug) {
689 System.err.println("Replacing " + inStream + " with: " + newIn);
690 System.err.println("Replacing " + outStream + " with: " + newOut);
691 }
692
693 inStream = newIn;
694
695 // Cleanup old stream
696 try {
744 * plain ones and then closes the SSL socket.
745 * If the reader thread attempts to read, or was reading, from
746 * the SSL socket (that is, it got to the read BEFORE replaceStreams()),
747 * the SSL socket close will cause the reader thread to
748 * get an EOF/exception and reexamine the input stream.
749 * If the reader thread sees a new stream, it reattempts the read.
750 * If the underlying socket is still alive, then the new read will succeed.
751 * If the underlying socket has been closed also, then the new read will
752 * fail and the reader thread exits.
753 * If the reader thread attempts to read, or was reading, from the plain
754 * socket (that is, it got to the read AFTER replaceStreams()), the
755 * SSL socket close will have no effect on the reader thread.
756 *
757 * The check for new stream is made only
758 * in the first attempt at reading a BER buffer; the reader should
759 * never be in midst of reading a buffer when a nonfatal close occurs.
760 * If this occurs, then the connection is in an inconsistent state and
761 * the safest thing to do is to shut it down.
762 */
763
764 private final Object pauseLock = new Object(); // lock for reader to wait on while paused
765 private boolean paused = false; // paused state of reader
766
767 /*
768 * Unpauses reader thread if it was paused
769 */
770 private void unpauseReader() throws IOException {
771 synchronized (pauseLock) {
772 if (paused) {
773 if (debug) {
774 System.err.println("Unpausing reader; read from: " +
775 inStream);
776 }
777 paused = false;
778 pauseLock.notify();
779 }
780 }
781 }
782
783 /*
784 * Pauses reader so that it stops reading from the input stream.
|