1// $OpenLDAP$ 2/* 3 * Copyright 2000-2021 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 19using namespace std; 20 21// TODO: How to handle unsolicited notifications, like notice of 22// disconnection 23 24LDAPMessageQueue::LDAPMessageQueue(LDAPRequest *req){ 25 DEBUG(LDAP_DEBUG_CONSTRUCT, "LDAPMessageQueue::LDAPMessageQueue()" << endl); 26 m_activeReq.push(req); 27 m_issuedReq.push_back(req); 28} 29 30LDAPMessageQueue::~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 40LDAPMsg *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 142LDAPRequest* 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 167LDAPRequestStack* LDAPMessageQueue::getRequestStack(){ 168 DEBUG(LDAP_DEBUG_TRACE,"LDAPMessageQueue::getRequestStack()" << endl); 169 return &m_activeReq; 170} 171 172