--- opal-3.6.2/src/sip/handlers.cxx.orig 2009-05-28 12:27:34.000000000 +0100 +++ opal-3.6.2/src/sip/handlers.cxx 2009-05-28 14:02:21.000000000 +0100 @@ -1465,6 +1465,16 @@ ////////////////////////////////////////////////////////////////// +/* All of the bwlow search loops run through the list with only + PSafeReference rather than PSafeReadOnly, even though they are + reading fields from the handler instances. We can get away with + this becuase the information being tested, e.g. AOR, is constant + for the life of the handler instance, once constructed. + + We need to use PSafeReference as there are some cases where + deadlocks can occur when locked handlers look for information + from other handlers. + */ unsigned SIPHandlersList::GetCount(SIP_PDU::Methods meth, const PString & eventPackage) const { unsigned count = 0; @@ -1493,11 +1503,12 @@ /** * Find the SIPHandler object with the specified callID */ -PSafePtr SIPHandlersList::FindSIPHandlerByCallID(const PString & callID, PSafetyMode m) +PSafePtr SIPHandlersList::FindSIPHandlerByCallID(const PString & callID, PSafetyMode mode) { - for (PSafePtr handler(*this, m); handler != NULL; ++handler) - if (callID == handler->GetCallID()) + for (PSafePtr handler(*this, PSafeReference); handler != NULL; ++handler) { + if (callID == handler->GetCallID() && handler.SetSafetyMode(mode)) return handler; + } return NULL; } @@ -1505,18 +1516,44 @@ /** * Find the SIPHandler object with the specified authRealm */ -PSafePtr SIPHandlersList::FindSIPHandlerByAuthRealm (const PString & authRealm, const PString & userName, PSafetyMode m) +PSafePtr SIPHandlersList::FindSIPHandlerByAuthRealm (const PString & authRealm, const PString & userName, PSafetyMode mode) { - PIPSocket::Address realmAddress; + PIPSocket::Address handlerRealmAddress; + PIPSocket::Address authRealmAddress(authRealm); + + // if username is specified, look for exact matches + if (!userName.IsEmpty()) { + + // look for a match to exact user name and realm + for (PSafePtr handler(*this, PSafeReference); handler != NULL; ++handler) { + if ( handler->GetUsername() == userName && + (handler->GetRealm().IsEmpty() || handler->GetRealm() == authRealm) && + handler.SetSafetyMode(mode)) + return handler; + } + + // look for a match to exact username and realm as hostname + for (PSafePtr handler(*this, PSafeReference); handler != NULL; ++handler) { + if (PIPSocket::GetHostAddress(handler->GetRealm(), handlerRealmAddress) && + handlerRealmAddress == authRealmAddress && + handler->GetUsername() == userName && + handler.SetSafetyMode(mode)) + return handler; + } + } - for (PSafePtr handler(*this, m); handler != NULL; ++handler) { - if (authRealm == handler->GetRealm() && (userName.IsEmpty() || userName == handler->GetUsername())) + // look for a match to exact realm + for (PSafePtr handler(*this, PSafeReference); handler != NULL; ++handler) { + if (handler->GetRealm() == authRealm && handler.SetSafetyMode(mode)) return handler; } - for (PSafePtr handler(*this, m); handler != NULL; ++handler) { - if (PIPSocket::GetHostAddress(handler->GetRealm(), realmAddress)) - if (realmAddress == PIPSocket::Address(authRealm) && (userName.IsEmpty() || userName == handler->GetUsername())) - return handler; + + // look for a match to exact realm as hostname + for (PSafePtr handler(*this, PSafeReference); handler != NULL; ++handler) { + if (PIPSocket::GetHostAddress(handler->GetRealm(), handlerRealmAddress) && + handlerRealmAddress == authRealmAddress && + handler.SetSafetyMode(mode)) + return handler; } return NULL; } @@ -1529,24 +1566,27 @@ * or 6001@seconix.com when registering 6001@seconix.com to * sip.seconix.com */ -PSafePtr SIPHandlersList::FindSIPHandlerByUrl(const PString & remoteAddress, SIP_PDU::Methods meth, PSafetyMode m) +PSafePtr SIPHandlersList::FindSIPHandlerByUrl(const PString & remoteAddress, SIP_PDU::Methods meth, PSafetyMode mode) { SIPURL remoteURL = remoteAddress; - for (PSafePtr handler(*this, m); handler != NULL; ++handler) { - if (meth == handler->GetMethod() && remoteURL == handler->GetAddressOfRecord()) + for (PSafePtr handler(*this, PSafeReference); handler != NULL; ++handler) { + if (handler->GetMethod() == meth && + handler->GetAddressOfRecord() == remoteURL && + handler.SetSafetyMode(mode)) return handler; } return NULL; } -PSafePtr SIPHandlersList::FindSIPHandlerByUrl(const PString & aor, SIP_PDU::Methods meth, const PString & eventPackage, PSafetyMode m) +PSafePtr SIPHandlersList::FindSIPHandlerByUrl(const PString & aor, SIP_PDU::Methods meth, const PString & eventPackage, PSafetyMode mode) { SIPURL aorURL = aor; - for (PSafePtr handler(*this, m); handler != NULL; ++handler) { - if (meth == handler->GetMethod() && + for (PSafePtr handler(*this, PSafeReference); handler != NULL; ++handler) { + if (handler->GetMethod() == meth && handler->GetAddressOfRecord() == aorURL && - handler->GetEventPackage() == eventPackage) + handler->GetEventPackage() == eventPackage && + handler.SetSafetyMode(mode)) return handler; } return NULL; @@ -1558,14 +1598,14 @@ * For example, in the above case, the name parameter * could be "sip.seconix.com" or "seconix.com". */ -PSafePtr SIPHandlersList::FindSIPHandlerByDomain(const PString & name, SIP_PDU::Methods meth, PSafetyMode m) +PSafePtr SIPHandlersList::FindSIPHandlerByDomain(const PString & name, SIP_PDU::Methods meth, PSafetyMode mode) { - for (PSafePtr handler(*this, m); handler != NULL; ++handler) { - - if ((handler->GetMethod() == meth) && - (handler->GetState() != SIPHandler::Unsubscribed) && + for (PSafePtr handler(*this, PSafeReference); handler != NULL; ++handler) { + if ( handler->GetMethod() == meth && + handler->GetState() != SIPHandler::Unsubscribed && (handler->GetAddressOfRecord().GetHostName() == name || - handler->GetAddressOfRecord().GetHostAddress().IsEquivalent(name))) + handler->GetAddressOfRecord().GetHostAddress().IsEquivalent(name)) && + handler.SetSafetyMode(mode)) return handler; } return NULL;