]> git.sur5r.net Git - openldap/blob - contrib/ldapc++/src/LDAPMessageQueue.cpp
Avoid double free of LDAPRequest
[openldap] / contrib / ldapc++ / src / LDAPMessageQueue.cpp
1 /*
2  * Copyright 2000, OpenLDAP Foundation, All Rights Reserved.
3  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
4  */
5
6
7 #include "config.h"
8 #include "debug.h"
9 #include "LDAPMessageQueue.h"
10 #include "LDAPRequest.h"
11 #include "LDAPResult.h"
12 #include "LDAPSearchReference.h"
13 #include "LDAPSearchRequest.h"
14 #include "LDAPUrl.h"
15 #include "LDAPUrlList.h"
16 #include "LDAPException.h"
17
18 using namespace std;
19
20 // TODO: How to handle unsolicited notifications, like notice of
21 //       disconnection
22
23 LDAPMessageQueue::LDAPMessageQueue(LDAPRequest *req){
24     DEBUG(LDAP_DEBUG_CONSTRUCT, "LDAPMessageQueue::LDAPMessageQueue()" << endl);
25         m_activeReq.push(req);
26     m_issuedReq.push_back(req);
27 }
28
29 LDAPMessageQueue::~LDAPMessageQueue(){
30     DEBUG(LDAP_DEBUG_DESTROY, "LDAPMessageQueue::~LDAPMessageQueue()" << endl);
31     for(LDAPRequestList::iterator i=m_issuedReq.begin(); 
32             i != m_issuedReq.end(); i++){
33         delete *i;
34     }
35     m_issuedReq.clear();
36 }
37
38
39 LDAPMsg *LDAPMessageQueue::getNext(){
40     DEBUG(LDAP_DEBUG_TRACE,"LDAPMessageQueue::getNext()" << endl);
41
42     if ( m_activeReq.empty() ) {
43         return 0;
44     }
45
46     LDAPRequest *req=m_activeReq.top();
47     LDAPMsg *ret=0;
48
49     try{
50         ret = req->getNextMessage();
51     }catch(LDAPException e){
52         //do some clean up
53         m_activeReq.pop();
54         throw;   
55     }
56
57     const LDAPConstraints *constr=req->getConstraints();
58     switch (ret->getMessageType()) {
59         case LDAPMsg::SEARCH_REFERENCE : 
60             if (constr->getReferralChase() ){
61                 //throws Exception (limit Exceeded)
62                 LDAPRequest *refReq=chaseReferral(ret);
63                 if(refReq != 0){
64                     m_activeReq.push(refReq);
65                     m_issuedReq.push_back(refReq);
66                     delete ret;
67                     return getNext();
68                 }
69             }
70             return ret;
71         break;
72         case LDAPMsg::SEARCH_ENTRY :
73             return ret;
74         break;
75         case LDAPMsg::SEARCH_DONE :
76             if(req->isReferral()){
77                 req->unbind();
78             }
79             switch ( ((LDAPResult*)ret)->getResultCode()) {
80                 case LDAPResult::REFERRAL :
81                     if(constr->getReferralChase()){
82                         //throws Exception (limit Exceeded)
83                         LDAPRequest *refReq=chaseReferral(ret);
84                         if(refReq != 0){
85                             m_activeReq.pop();
86                             m_activeReq.push(refReq);
87                             m_issuedReq.push_back(refReq);
88                             delete ret;
89                             return getNext();
90                         }
91                     }    
92                     return ret;
93                 break;
94                 case LDAPResult::SUCCESS :
95                     if(req->isReferral()){
96                         delete ret;
97                         m_activeReq.pop();
98                         return getNext();
99                     }else{
100                         m_activeReq.pop();
101                         return ret;
102                     }
103                 break;
104                 default:
105                     m_activeReq.pop();
106                     return ret;
107                 break;
108             }
109         break;
110         //must be some kind of LDAPResultMessage
111         default:
112             if(req->isReferral()){
113                 req->unbind();
114             }
115             LDAPResult* res_p=(LDAPResult*)ret;
116             switch (res_p->getResultCode()) {
117                 case LDAPResult::REFERRAL :
118                     if(constr->getReferralChase()){
119                         //throws Exception (limit Exceeded)
120                         LDAPRequest *refReq=chaseReferral(ret);
121                         if(refReq != 0){
122                             m_activeReq.pop();
123                             m_activeReq.push(refReq);
124                             m_issuedReq.push_back(refReq);
125                             delete ret;
126                             return getNext();
127                         }
128                     }    
129                     return ret;
130                 break;
131                 default:
132                     m_activeReq.pop();
133                     return ret;
134             }
135         break;
136     }
137 }
138
139 // TODO Maybe moved to LDAPRequest::followReferral seems more reasonable
140 //there
141 LDAPRequest* LDAPMessageQueue::chaseReferral(LDAPMsg* ref){
142     DEBUG(LDAP_DEBUG_TRACE,"LDAPMessageQueue::chaseReferral()" << endl);
143     LDAPRequest *req=m_activeReq.top();
144     LDAPRequest *refReq=req->followReferral(ref);
145     if(refReq !=0){
146         if(refReq->getConstraints()->getHopLimit() < refReq->getHopCount()){
147             delete(refReq);
148             throw LDAPException(LDAP_REFERRAL_LIMIT_EXCEEDED);
149         }
150         if(refReq->isCycle()){
151             delete(refReq);
152             throw LDAPException(LDAP_CLIENT_LOOP);
153         }
154         try {
155             refReq->sendRequest();
156             return refReq;
157         }catch (LDAPException e){
158             DEBUG(LDAP_DEBUG_TRACE,"   caught exception" << endl);
159             return 0;
160         }
161     }else{ 
162         return 0;
163     }
164 }
165
166 LDAPRequestStack* LDAPMessageQueue::getRequestStack(){
167     DEBUG(LDAP_DEBUG_TRACE,"LDAPMessageQueue::getRequestStack()" << endl);
168     return &m_activeReq;
169 }
170