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