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