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