]> git.sur5r.net Git - openldap/blob - contrib/ldapc++/src/LDAPMessageQueue.cpp
initial support for SASL
[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         delete req;
54         m_activeReq.top();
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