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