From 90a85f0fed34b0a7d6db93022074a39a17ad27b7 Mon Sep 17 00:00:00 2001
From: boli <boli@localhost>
Date: Fri, 24 Apr 2009 17:05:14 +0000
Subject: [PATCH] Fix for issue where unit tests hang when the startTLS extended operation is used.

---
 opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java |  110 +++++++++++++++++++++++++++++++++----------------------
 1 files changed, 66 insertions(+), 44 deletions(-)

diff --git a/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java b/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
index 57b27e5..d0cd61f 100644
--- a/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
+++ b/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
@@ -50,6 +50,7 @@
 
 import org.opends.messages.Message;
 import org.opends.messages.MessageBuilder;
+import static org.opends.messages.CoreMessages.ERR_ENQUEUE_BIND_IN_PROGRESS;
 import org.opends.server.api.ClientConnection;
 import org.opends.server.api.ConnectionHandler;
 import org.opends.server.core.AbandonOperationBasis;
@@ -76,24 +77,9 @@
 import org.opends.server.protocols.asn1.ASN1;
 import org.opends.server.protocols.asn1.ASN1ByteChannelReader;
 import org.opends.server.protocols.asn1.ASN1Writer;
-import org.opends.server.types.AbstractOperation;
-import org.opends.server.types.ByteString;
-import org.opends.server.types.ByteStringBuilder;
-import org.opends.server.types.CancelRequest;
-import org.opends.server.types.CancelResult;
-import org.opends.server.types.Control;
-import org.opends.server.types.DN;
-import org.opends.server.types.DebugLogLevel;
-import org.opends.server.types.DirectoryException;
-import org.opends.server.types.DisconnectReason;
-import org.opends.server.types.IntermediateResponse;
-import org.opends.server.types.Operation;
-import org.opends.server.types.OperationType;
-import org.opends.server.types.ResultCode;
-import org.opends.server.types.SearchResultEntry;
-import org.opends.server.types.SearchResultReference;
+import org.opends.server.types.*;
 import org.opends.server.util.TimeThread;
-
+import static org.opends.server.util.ServerConstants.OID_START_TLS_REQUEST;
 
 
 /**
@@ -200,9 +186,9 @@
 
   private final RedirectingByteChannel saslChannel;
   private final RedirectingByteChannel tlsChannel;
-  private ConnectionSecurityProvider activeProvider = null;
-  private ConnectionSecurityProvider tlsPendingProvider = null;
-  private ConnectionSecurityProvider saslPendingProvider = null;
+  private volatile ConnectionSecurityProvider activeProvider = null;
+  private volatile ConnectionSecurityProvider tlsPendingProvider = null;
+  private volatile ConnectionSecurityProvider saslPendingProvider = null;
 
   // Statistics for the processed operations
   private OperationMonitor addMonitor;
@@ -1419,12 +1405,15 @@
    */
   public boolean processDataRead()
   {
-    if (this.saslPendingProvider != null)
-    {
-      enableSASL();
-    }
     while (true)
     {
+      if(bindOrStartTLSInProgress.get())
+      {
+        // We should wait for the bind or startTLS to finish before
+        // reading any more data off the socket.
+        return true;
+      }
+
       try
       {
         int result = asn1Reader.processChannelData();
@@ -1541,6 +1530,14 @@
     // terminated.
     try
     {
+      if(bindOrStartTLSInProgress.get() ||
+          (saslBindInProgress.get() &&
+              message.getProtocolOpType() != OP_TYPE_BIND_REQUEST))
+      {
+        throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
+            ERR_ENQUEUE_BIND_IN_PROGRESS.get());
+      }
+
       boolean result;
       switch (message.getProtocolOpType())
       {
@@ -1564,7 +1561,22 @@
         return result;
       case OP_TYPE_BIND_REQUEST:
         if (keepStats) this.bindMonitor.start();
+        bindOrStartTLSInProgress.set(true);
+        if(message.getBindRequestProtocolOp().
+            getAuthenticationType() == AuthenticationType.SASL)
+        {
+          saslBindInProgress.set(true);
+        }
         result = processBindRequest(message, opControls);
+        if(!result)
+        {
+          bindOrStartTLSInProgress.set(false);
+          if(message.getBindRequestProtocolOp().
+              getAuthenticationType() == AuthenticationType.SASL)
+          {
+            saslBindInProgress.set(false);
+          }
+        }
         if (keepStats)
         {
           this.bindMonitor.stop();
@@ -1591,7 +1603,18 @@
         return result;
       case OP_TYPE_EXTENDED_REQUEST:
         if (keepStats) this.extendedMonitor.start();
+        if(message.getExtendedRequestProtocolOp().getOID().equals(
+            OID_START_TLS_REQUEST))
+        {
+          bindOrStartTLSInProgress.set(true);
+        }
         result = processExtendedRequest(message, opControls);
+        if(!result &&
+            message.getExtendedRequestProtocolOp().getOID().equals(
+                OID_START_TLS_REQUEST))
+        {
+          bindOrStartTLSInProgress.set(false);
+        }
         if (keepStats)
         {
           this.extendedMonitor.stop();
@@ -2447,26 +2470,6 @@
 
 
   /**
-   * Sends a response to the client in the clear rather than through the
-   * encrypted channel. This should only be used when processing the
-   * StartTLS extended operation to send the response in the clear after
-   * the TLS negotiation has already been initiated.
-   *
-   * @param operation
-   *          The operation for which to send the response in the clear.
-   * @throws DirectoryException
-   *           If a problem occurs while sending the response in the
-   *           clear.
-   */
-  public void sendClearResponse(Operation operation)
-      throws DirectoryException
-  {
-    sendLDAPMessage(operationToResponseLDAPMessage(operation));
-  }
-
-
-
-  /**
    * Retrieves the length of time in milliseconds that this client
    * connection has been idle. <BR>
    * <BR>
@@ -2649,4 +2652,23 @@
     this.moddnMonitor = OperationMonitor.getOperationMonitor(MODIFY_DN);
     this.unbindMonitor = OperationMonitor.getOperationMonitor(UNBIND);
   }
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public void finishBindOrStartTLS()
+  {
+    if(this.tlsPendingProvider != null)
+    {
+      enableTLS();
+    }
+
+    if (this.saslPendingProvider != null)
+    {
+      enableSASL();
+    }
+
+    super.finishBindOrStartTLS();
+  }
 }

--
Gitblit v1.10.0