]> git.sur5r.net Git - openldap/blob - contrib/ldapc++/src/LDAPMessageQueue.cpp
6d0e614d6f9d39ef2dcb536164bab8eae87e6eee
[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 // 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         LDAPMessage *msg;
43     LDAPRequest *req=m_activeReq.top();
44     int msg_id = req->getMsgID();
45         int res;
46     const  LDAPAsynConnection *con=req->getConnection();
47     res=ldap_result(con->getSessionHandle(),msg_id,0,0,&msg);
48     if (res <= 0){
49         if(msg != 0){
50             ldap_msgfree(msg);
51         }
52                 throw  LDAPException(con);
53         }else{  
54         const LDAPConstraints *constr=req->getConstraints();
55         LDAPMsg *ret=0;
56         //this can  throw an exception (Decoding Error)
57         try{
58             ret = LDAPMsg::create(req,msg);
59             ldap_msgfree(msg);
60         }catch(LDAPException e){
61             //do some clean up
62             delete req;
63             m_activeReq.top();
64             throw;   
65         }
66         switch (ret->getMessageType()) {
67             case LDAPMsg::SEARCH_REFERENCE : 
68                 if (constr->getReferralChase() ){
69                     //throws Exception (limit Exceeded)
70                     LDAPRequest *refReq=chaseReferral(ret);
71                     if(refReq != 0){
72                         m_activeReq.push(refReq);
73                         m_issuedReq.push_back(refReq);
74                         delete ret;
75                         return getNext();
76                     }
77                 }
78                 return ret;
79             break;
80             case LDAPMsg::SEARCH_ENTRY :
81                 return ret;
82             break;
83             case LDAPMsg::SEARCH_DONE :
84                 if(req->isReferral()){
85                     req->unbind();
86                 }
87                 switch ( ((LDAPResult*)ret)->getResultCode()) {
88                     case LDAPResult::REFERRAL :
89                         if(constr->getReferralChase()){
90                             //throws Exception (limit Exceeded)
91                             LDAPRequest *refReq=chaseReferral(ret);
92                             if(refReq != 0){
93                                 m_activeReq.pop();
94                                 m_activeReq.push(refReq);
95                                 m_issuedReq.push_back(refReq);
96                                 delete ret;
97                                 return getNext();
98                             }
99                         }    
100                         return ret;
101                     break;
102                     case LDAPResult::SUCCESS :
103                         if(req->isReferral()){
104                             delete ret;
105                             m_activeReq.pop();
106                             return getNext();
107                         }else{
108                             m_activeReq.pop();
109                             return ret;
110                         }
111                     break;
112                     default:
113                         m_activeReq.pop();
114                         return ret;
115                     break;
116                 }
117             break;
118             //must be some kind of LDAPResultMessage
119             default:
120                 if(req->isReferral()){
121                     req->unbind();
122                 }
123                 LDAPResult* res_p=(LDAPResult*)ret;
124                 switch (res_p->getResultCode()) {
125                     case LDAPResult::REFERRAL :
126                         DEBUG(LDAP_DEBUG_TRACE, 
127                                "referral chasing to be implemented" 
128                                 << endl);
129                         if(constr->getReferralChase()){
130                             //throws Exception (limit Exceeded)
131                             LDAPRequest *refReq=chaseReferral(ret);
132                             if(refReq != 0){
133                                 m_activeReq.pop();
134                                 m_activeReq.push(refReq);
135                                 m_issuedReq.push_back(refReq);
136                                 delete ret;
137                                 return getNext();
138                             }
139                         }    
140                         return ret;
141                     break;
142                     default:
143                         m_activeReq.pop();
144                         return ret;
145                 }
146             break;
147         }
148         }       
149 }
150
151 // TODO Maybe moved to LDAPRequest::followReferral seems more reasonable
152 //there
153 LDAPRequest* LDAPMessageQueue::chaseReferral(LDAPMsg* ref){
154     DEBUG(LDAP_DEBUG_TRACE,"LDAPMessageQueue::chaseReferra()" << endl);
155     LDAPRequest *req=m_activeReq.top();
156     LDAPRequest *refReq=req->followReferral(ref);
157     if(refReq !=0){
158         if(refReq->getConstraints()->getHopLimit() < refReq->getHopCount()){
159             delete(refReq);
160             throw LDAPException(LDAP_REFERRAL_LIMIT_EXCEEDED);
161         }
162         if(refReq->isCycle()){
163             delete(refReq);
164             throw LDAPException(LDAP_CLIENT_LOOP);
165         }
166         try {
167             refReq->sendRequest();
168             return refReq;
169         }catch (LDAPException e){
170             DEBUG(LDAP_DEBUG_TRACE,"   caught exception" << endl);
171             return 0;
172         }
173     }else{ 
174         return 0;
175     }
176 }
177
178 LDAPRequestStack* LDAPMessageQueue::getRequestStack(){
179     DEBUG(LDAP_DEBUG_TRACE,"LDAPMessageQueue::getRequestStack()" << endl);
180     return &m_activeReq;
181 }
182