]> git.sur5r.net Git - openldap/blobdiff - contrib/ldapc++/src/LDAPMessageQueue.cpp
Entry rwlock is no longer needed as concurrency is managed
[openldap] / contrib / ldapc++ / src / LDAPMessageQueue.cpp
index 34101ec89b5c37af9219a7a32728e34082d6453e..2668609e8768d861a28bf41d412e556ea23c97bd 100644 (file)
@@ -3,7 +3,6 @@
  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
  */
 
-// $Id: LDAPMessageQueue.cpp,v 1.17 2000/08/31 17:43:48 rhafer Exp $
 
 #include "config.h"
 #include "debug.h"
 #include "LDAPUrlList.h"
 #include "LDAPException.h"
 
-// TODO: How to handel unsolicited notifications, like notice of
+using namespace std;
+
+// TODO: How to handle unsolicited notifications, like notice of
 //       disconnection
 
 LDAPMessageQueue::LDAPMessageQueue(LDAPRequest *req){
-    DEBUG(LDAP_DEBUG_TRACE, "LDAPMessageQueue::LDAPMessageQueue()" << endl);
-       m_reqQueue.push(req);
+    DEBUG(LDAP_DEBUG_CONSTRUCT, "LDAPMessageQueue::LDAPMessageQueue()" << endl);
+       m_activeReq.push(req);
+    m_issuedReq.push_back(req);
 }
 
 LDAPMessageQueue::~LDAPMessageQueue(){
-    DEBUG(LDAP_DEBUG_TRACE, "LDAPMessageQueue::~LDAPMessageQueue()" << endl);
-    LDAPRequest *req;
-    while(! m_reqQueue.empty()){
-        req=m_reqQueue.top();
-        delete req;
-        m_reqQueue.pop();
+    DEBUG(LDAP_DEBUG_DESTROY, "LDAPMessageQueue::~LDAPMessageQueue()" << endl);
+    for(LDAPRequestList::iterator i=m_issuedReq.begin(); 
+            i != m_issuedReq.end(); i++){
+        delete *i;
     }
+    m_issuedReq.clear();
 }
 
+
 LDAPMsg *LDAPMessageQueue::getNext(){
     DEBUG(LDAP_DEBUG_TRACE,"LDAPMessageQueue::getNext()" << endl);
-       LDAPMessage *msg;
-    LDAPRequest *req=m_reqQueue.top();
-    const LDAPConstraints *constr=req->getConstraints();
+    LDAPMessage *msg;
+    LDAPRequest *req=m_activeReq.top();
     int msg_id = req->getMsgID();
-       int res;
+    int res;
     const  LDAPAsynConnection *con=req->getConnection();
-       res=ldap_result(con->getSessionHandle(),msg_id,0,0,&msg);
-       if (res <= 0){
-        ldap_msgfree(msg);
-               throw  LDAPException(con);
-       }else{  
-               LDAPMsg *ret = LDAPMsg::create(req,msg);
-        ldap_msgfree(msg);
+    res=ldap_result(con->getSessionHandle(),msg_id,0,0,&msg);
+    if (res <= 0){
+        if(msg != 0){
+            ldap_msgfree(msg);
+        }
+       throw  LDAPException(con);
+    }else{     
+        const LDAPConstraints *constr=req->getConstraints();
+        LDAPMsg *ret=0;
+        //this can  throw an exception (Decoding Error)
+        try{
+            ret = LDAPMsg::create(req,msg);
+            ldap_msgfree(msg);
+        }catch(LDAPException e){
+            //do some clean up
+            delete req;
+            m_activeReq.top();
+            throw;   
+        }
         switch (ret->getMessageType()) {
             case LDAPMsg::SEARCH_REFERENCE : 
                 if (constr->getReferralChase() ){
-                    LDAPSearchReference *ref=(LDAPSearchReference *)ret;
-                    LDAPRequest *refReq=chaseReferral(ref->getURLs());
+                    //throws Exception (limit Exceeded)
+                    LDAPRequest *refReq=chaseReferral(ret);
                     if(refReq != 0){
-                        m_reqQueue.push(refReq);
+                        m_activeReq.push(refReq);
+                        m_issuedReq.push_back(refReq);
+                        delete ret;
                         return getNext();
                     }
                 }
@@ -68,59 +83,89 @@ LDAPMsg *LDAPMessageQueue::getNext(){
                 return ret;
             break;
             case LDAPMsg::SEARCH_DONE :
-                if (req->isReferral()){
-                    LDAPResult* res_p=(LDAPResult*)ret;
-                    switch (res_p->getResultCode()) {
-                        case LDAPResult::REFERRAL :
-                            DEBUG(LDAP_DEBUG_TRACE, 
-                                    "referral chasing to be implemented" 
-                                    << endl);
-                            return ret;
-                        break;
-                        default:
+                if(req->isReferral()){
+                    req->unbind();
+                }
+                switch ( ((LDAPResult*)ret)->getResultCode()) {
+                    case LDAPResult::REFERRAL :
+                        if(constr->getReferralChase()){
+                            //throws Exception (limit Exceeded)
+                            LDAPRequest *refReq=chaseReferral(ret);
+                            if(refReq != 0){
+                                m_activeReq.pop();
+                                m_activeReq.push(refReq);
+                                m_issuedReq.push_back(refReq);
+                                delete ret;
+                                return getNext();
+                            }
+                        }    
+                        return ret;
+                    break;
+                    case LDAPResult::SUCCESS :
+                        if(req->isReferral()){
+                            delete ret;
+                            m_activeReq.pop();
+                            return getNext();
+                        }else{
+                            m_activeReq.pop();
                             return ret;
-                    }
-                    delete req;
-                    m_reqQueue.pop();
-                    return getNext();
-                }else{
-                    return ret;
+                        }
+                    break;
+                    default:
+                        m_activeReq.pop();
+                        return ret;
+                    break;
                 }
             break;
             //must be some kind of LDAPResultMessage
             default:
+                if(req->isReferral()){
+                    req->unbind();
+                }
                 LDAPResult* res_p=(LDAPResult*)ret;
                 switch (res_p->getResultCode()) {
                     case LDAPResult::REFERRAL :
-                        DEBUG(LDAP_DEBUG_TRACE, 
-                               "referral chasing to be implemented" 
-                                << endl);
-                        //for now just end it here
-                        delete req;
+                        if(constr->getReferralChase()){
+                            //throws Exception (limit Exceeded)
+                            LDAPRequest *refReq=chaseReferral(ret);
+                            if(refReq != 0){
+                                m_activeReq.pop();
+                                m_activeReq.push(refReq);
+                                m_issuedReq.push_back(refReq);
+                                delete ret;
+                                return getNext();
+                            }
+                        }    
                         return ret;
                     break;
                     default:
-                        delete req;
-                        m_reqQueue.pop();
+                        m_activeReq.pop();
                         return ret;
                 }
             break;
         }
-       }       
+    }  
 }
 
 // TODO Maybe moved to LDAPRequest::followReferral seems more reasonable
 //there
-LDAPRequest* LDAPMessageQueue::chaseReferral(LDAPUrlList *refs){
+LDAPRequest* LDAPMessageQueue::chaseReferral(LDAPMsg* ref){
     DEBUG(LDAP_DEBUG_TRACE,"LDAPMessageQueue::chaseReferra()" << endl);
-    LDAPRequest *req=m_reqQueue.top();
-    LDAPRequest *refReq=req->followReferral(refs);
+    LDAPRequest *req=m_activeReq.top();
+    LDAPRequest *refReq=req->followReferral(ref);
     if(refReq !=0){
+        if(refReq->getConstraints()->getHopLimit() < refReq->getHopCount()){
+            delete(refReq);
+            throw LDAPException(LDAP_REFERRAL_LIMIT_EXCEEDED);
+        }
+        if(refReq->isCycle()){
+            delete(refReq);
+            throw LDAPException(LDAP_CLIENT_LOOP);
+        }
         try {
             refReq->sendRequest();
             return refReq;
         }catch (LDAPException e){
-            cout << e << endl;
             DEBUG(LDAP_DEBUG_TRACE,"   caught exception" << endl);
             return 0;
         }
@@ -130,6 +175,7 @@ LDAPRequest* LDAPMessageQueue::chaseReferral(LDAPUrlList *refs){
 }
 
 LDAPRequestStack* LDAPMessageQueue::getRequestStack(){
-    return &m_reqQueue;
+    DEBUG(LDAP_DEBUG_TRACE,"LDAPMessageQueue::getRequestStack()" << endl);
+    return &m_activeReq;
 }