[asterisk-scf-commits] asterisk-scf/integration/sip.git branch "sip-configuration-refactor" updated.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Wed May 11 15:12:14 CDT 2011


branch "sip-configuration-refactor" has been updated
       via  66e5749ebbdb3b8efa2e0facb8c93f5c718f4c33 (commit)
       via  76b5fcc14ad87fca2e9aac2c4f7645e4580ab2c1 (commit)
       via  53eea482a563ce1e74f78c7c1af1df61e82faad4 (commit)
       via  9713fcc350ecc28c95ee74154806e8a36033cdc4 (commit)
      from  4463bb246f0b492894df7341e7023f11c4d5cd73 (commit)

Summary of changes:
 src/SipConfiguration.cpp |  397 +++++++++++++++++++---------------------------
 1 files changed, 163 insertions(+), 234 deletions(-)


- Log -----------------------------------------------------------------
commit 66e5749ebbdb3b8efa2e0facb8c93f5c718f4c33
Merge: 9713fcc 76b5fcc
Author: Brent Eagles <beagles at digium.com>
Date:   Wed May 11 17:35:56 2011 -0230

    Added command lists to collect updates and update the configuration objects
    under a single lock, preserving consistency while allowing concurrency.


commit 76b5fcc14ad87fca2e9aac2c4f7645e4580ab2c1
Author: Brent Eagles <beagles at digium.com>
Date:   Wed May 11 17:30:45 2011 -0230

    Added use of bind and command lists to collect and process configuration
    updates "relatively" atomically.

diff --git a/src/SipConfiguration.cpp b/src/SipConfiguration.cpp
index a5d2cd3..0354964 100644
--- a/src/SipConfiguration.cpp
+++ b/src/SipConfiguration.cpp
@@ -55,13 +55,10 @@ namespace SipSessionManager
  **/
 
 /**
- *
  * A generic instance of the createGroupTemplate() that creates a new, empty instance of a named group.
  *
  * @param group an instance of the group to create a template for.
- *
  * @return a new instance of type T that may contain members copied from the group parameter.
- *
  **/
 template <typename T>
 T createGroupTemplate(const T& group)
@@ -269,6 +266,7 @@ public:
         // here is a little suspect.
         //
         RegExSeq destinations;
+        bool updateSystem = !updates.empty();
         {
             boost::unique_lock<boost::shared_mutex> lock(mLock);
             for (UpdateCommandList::const_iterator op = updates.begin();
@@ -278,10 +276,15 @@ public:
                 UpdateCommand command = *op;
                 command();
             }
-            mFactory->generateRoutingDestinations(destinations);
+            if (updateSystem)
+            {
+                mFactory->generateRoutingDestinations(destinations);
+            }
+        }
+        if (updateSystem)
+        {
+            mRegistry->setEndpointLocatorDestinationIds(mRoutingId, destinations);
         }
-        
-        mRegistry->setEndpointLocatorDestinationIds(mRoutingId, destinations);
     }
 
 private:
@@ -297,11 +300,7 @@ class ConfigBase
 public:
     virtual ~ConfigBase() {}
 
-    virtual SipConfigurationGroupPtr getGroup() const = 0;
-
     virtual SipConfigurationItemVisitorPtr getVisitor() { return 0; }
-
-    virtual void updated() { }
 };
 typedef boost::shared_ptr<ConfigBase> ConfigBasePtr;
 
@@ -320,26 +319,17 @@ class UDPTransportConfig : public ConfigBase, public boost::enable_shared_from_t
         {
         }
 
-        ~Visitor()
-        {
-            try
-            {
-                mConfig->updated();
-            }
-            catch(...)
-            {
-                //
-                // See comment in the EndpointConfigHelper's Visitor::~Visitor.
-                //
-            }
-        }
-
         void visitSipHostItem(const SipHostItemPtr& hostItem)
         {
+            //
+            // Where the UDPTransportConfig only has one variable that is configurable,
+            // we can initiate a complete update directly.
+            //
             mConfig->update(hostItem);
         }
     private:
         boost::shared_ptr<UDPTransportConfig> mConfig;
+        
     };
     
 public:
@@ -349,8 +339,7 @@ public:
     UDPTransportConfig(const SipUDPTransportGroupPtr& group, PJSipManager* manager) :
         mGroup(group),
         mManager(manager),
-        mTransport(0),
-        mNeedsUpdating(false)
+        mTransport(0)
     {
     };
 
@@ -367,54 +356,25 @@ public:
 
     SipConfigurationItemVisitorPtr getVisitor()
     {
-        
         return new Visitor(shared_from_this());
     }
 
     void update(const SipHostItemPtr& hostItem)
     {
+        pjsip_transport* oldTransport = 0;
         boost::unique_lock<boost::shared_mutex> lock(mLock);
-        mNeedsUpdating = (mAddress != hostItem->host || mPort != hostItem->port);
-        if (mNeedsUpdating)
+        if (mAddress != hostItem->host || mPort != hostItem->port)
         {
             mAddress = hostItem->host;
             mPort = hostItem->port;
-        }
-    }
-
-    void updated()
-    {
-        string hostname;
-        int port;
-        {
-            boost::unique_lock<boost::shared_mutex> lock(mLock);
-            if (!mNeedsUpdating)
-            {
-                return;
-            }
-            mNeedsUpdating = false;
-            hostname = mAddress;
-            port = mPort;
-        }
-        
-        pjsip_transport *newTransport =  mManager->createUDPTransport(hostname, port);
-        pjsip_transport *oldTransport = 0;
-
-        {
-            boost::unique_lock<boost::shared_mutex> lock(mLock);
             oldTransport = mTransport;
-            mTransport = newTransport;
+            mTransport = mManager->createUDPTransport(mAddress, mPort);
         }
-
         if (oldTransport)
         {
             pjsip_transport_shutdown(oldTransport);
         }
-    }
-
-    SipConfigurationGroupPtr getGroup() const
-    {
-        return mGroup;
+        
     }
         
     SipUDPTransportGroupPtr getTypedGroup() const
@@ -446,8 +406,6 @@ private:
      * Transport within pjsip.
      */
     pjsip_transport *mTransport;
-
-    bool mNeedsUpdating;
 };
 typedef boost::shared_ptr<UDPTransportConfig> UDPTransportConfigPtr;
 typedef std::map<std::string, UDPTransportConfigPtr> UDPTransportMap;
@@ -462,22 +420,12 @@ class TCPTransportConfig : public ConfigBase, public boost::enable_shared_from_t
         {
         }
 
-        ~Visitor()
-        {
-            try
-            {
-                mConfig->updated();
-            }
-            catch(...)
-            {
-                //
-                // See comment in the EndpointConfigHelper's Visitor::~Visitor.
-                //
-            }
-        }
-
         void visitSipHostItem(const SipHostItemPtr& hostItem)
         {
+            //
+            // Where the TCPTransportConfig only has one variable that is configurable,
+            // we can initiate a complete update directly.
+            //
             mConfig->update(hostItem);
         }
     private:
@@ -491,8 +439,7 @@ public:
     TCPTransportConfig(const SipTCPTransportGroupPtr& group, PJSipManager* manager) :
         mGroup(group),
         mManager(manager),
-        mTransportFactory(0),
-        mNeedsUpdating(false)
+        mTransportFactory(0)
     {
     };
 
@@ -515,49 +462,14 @@ public:
     void update(const SipHostItemPtr& hostItem)
     {
         boost::unique_lock<boost::shared_mutex> lock(mLock);
-        mNeedsUpdating = (mAddress != hostItem->host || mPort != hostItem->port);
-        if (mNeedsUpdating)
+        if (mAddress != hostItem->host || mPort != hostItem->port)
         {
             mAddress = hostItem->host;
             mPort = hostItem->port;
+            mTransportFactory = mManager->createTCPTransport(mAddress, mPort);
         }
     }
 
-    void updated()
-    {
-        string hostname;
-        int port;
-        {
-            boost::unique_lock<boost::shared_mutex> lock(mLock);
-            if (!mNeedsUpdating)
-            {
-                return;
-            }
-            mNeedsUpdating = false;
-            hostname = mAddress;
-            port = mPort;
-        }
-        
-        pjsip_tpfactory* newTransportFactory =  mManager->createTCPTransport(hostname, port);
-        pjsip_tpfactory* oldTransport = 0;
-
-        {
-            boost::unique_lock<boost::shared_mutex> lock(mLock);
-            oldTransport = mTransportFactory;
-            mTransportFactory = newTransportFactory;
-        }
-
-        //
-        // XXX and now it would be nice if we could do something with the transport.
-        //
-        oldTransport = 0;
-    }
-
-    SipConfigurationGroupPtr getGroup() const
-    {
-        return mGroup;
-    }
-    
     SipTCPTransportGroupPtr getTypedGroup() const
     {
         return mGroup;
@@ -587,8 +499,6 @@ private:
      * Transport factory within pjsip.
      */
     pjsip_tpfactory *mTransportFactory;
-
-    bool mNeedsUpdating;
 };
 typedef boost::shared_ptr<TCPTransportConfig> TCPTransportConfigPtr;
 typedef std::map<std::string, TCPTransportConfigPtr> TCPTransportMap;
@@ -607,7 +517,7 @@ class TLSTransportConfig : public ConfigBase, public boost::enable_shared_from_t
         {
             try
             {
-                mConfig->updated();
+                mConfig->updated(mUpdates);
             }
             catch(...)
             {
@@ -619,25 +529,26 @@ class TLSTransportConfig : public ConfigBase, public boost::enable_shared_from_t
 
         void visitSipHostItem(const SipHostItemPtr& hostItem)
         {
-            mConfig->update(hostItem);
+            mUpdates.push_back(boost::bind(&TLSTransportConfig::updateHost, mConfig, hostItem));
         }
 
         void visitSipCryptoCertificateItem(const SipCryptoCertificateItemPtr& certificateItem)
         {
-            mConfig->update(certificateItem);
+            mUpdates.push_back(boost::bind(&TLSTransportConfig::updateCertificate, mConfig, certificateItem));
         }
 
         void visitSipCryptoRequirementsItem(const SipCryptoRequirementsItemPtr& requirementsItem)
         {
-            mConfig->update(requirementsItem);
+            mUpdates.push_back(boost::bind(&TLSTransportConfig::updateRequirements, mConfig, requirementsItem));
         }
         
         void visitSipCryptoItem(const ::AsteriskSCF::SIP::V1::SipCryptoItemPtr& cryptoItem)
         {
-            mConfig->update(cryptoItem);
+            mUpdates.push_back(boost::bind(&TLSTransportConfig::updateCrypto, mConfig, cryptoItem));
         }
         
     private:
+        UpdateCommandList mUpdates;
         boost::shared_ptr<TLSTransportConfig> mConfig;
     };
 public:
@@ -669,44 +580,39 @@ public:
         return new Visitor(shared_from_this());
     }
 
-    void update(const SipHostItemPtr& hostItem)
+    void updateHost(const SipHostItemPtr& hostItem)
     {
-        boost::unique_lock<boost::shared_mutex> lock(mLock);
-        
-        mNeedsUpdating = (mAddress != hostItem->host || mPort != hostItem->port);
-        if (mNeedsUpdating)
+        if (mAddress != hostItem->host || mPort != hostItem->port)
         {
             mAddress = hostItem->host;
             mPort = hostItem->port;
+            mNeedsUpdating = true;
         }
     }
 
-    void update(const SipCryptoCertificateItemPtr& certificate)
+    void updateCertificate(const SipCryptoCertificateItemPtr& certificate)
     {
+        mNeedsUpdating = true;
         //
         // TODO: This is a little sketchy. We need to make sure that the certificateItem CAN NOT GO AWAY whilst
         // mTLSSettings might get used. I'm referring to the fact that pj_str doesn't copy the string.
         //
-        boost::unique_lock<boost::shared_mutex> lock(mLock);
-        mNeedsUpdating = true;
         mTLSSettings.ca_list_file = pj_str((char*)certificate->certificateAuthority.c_str());
         mTLSSettings.cert_file = pj_str((char*)certificate->certificate.c_str());
         mTLSSettings.privkey_file = pj_str((char*)certificate->privateKey.c_str());
         mTLSSettings.password = pj_str((char*)certificate->privateKeyPassword.c_str());
     }
 
-    void update(const SipCryptoRequirementsItemPtr& requirements)
+    void updateRequirements(const SipCryptoRequirementsItemPtr& requirements)
     {
-        boost::unique_lock<boost::shared_mutex> lock(mLock);
         mNeedsUpdating = true;
         mTLSSettings.verify_server = (requirements->requireVerifiedServer) ? PJ_TRUE : PJ_FALSE;
         mTLSSettings.verify_client = (requirements->requireVerifiedClient) ? PJ_TRUE : PJ_FALSE;
         mTLSSettings.require_client_cert = (requirements->requireClientCertificate) ? PJ_TRUE : PJ_FALSE;
     }
 
-    void update(const SipCryptoItemPtr& crypto)
+    void updateCrypto(const SipCryptoItemPtr& crypto)
     {
-        boost::unique_lock<boost::shared_mutex> lock(mLock);
         mNeedsUpdating = true;
         if (crypto->protocolMethod == PROTOCOLMETHODUNSPECIFIED)
         {
@@ -733,20 +639,22 @@ public:
         mTLSSettings.timeout.sec = crypto->timeout;
     }
 
-    void updated()
+    void updated(const UpdateCommandList& updates)
     {
         boost::unique_lock<boost::shared_mutex> lock(mLock);
+        for (UpdateCommandList::const_iterator op = updates.begin();
+             op != updates.end();
+             ++op)
+        {
+            UpdateCommand command = *op;
+            command();
+        }
         if (mNeedsUpdating)
         {
             mNeedsUpdating = false;
             mTransportFactory = mManager->createTLSTransport(mAddress, mPort, &mTLSSettings);
         }
     }
-    
-    SipConfigurationGroupPtr getGroup() const
-    {
-        return mGroup;
-    }
 
     SipTLSTransportGroupPtr getTypedGroup() const
     {
@@ -814,10 +722,8 @@ public:
     typedef std::map<std::string, SipDomainGroupPtr> DomainMap;
     typedef std::map<std::string, SipEndpointGroupPtr> EndpointMap;
     
-    ConfigurationData(PJSipManager* manager, 
-        const boost::shared_ptr<SipEndpointFactory>& factory,
-        const std::string& routingId, 
-        const LocatorRegistrySmartPrx& registry) : 
+    ConfigurationData(PJSipManager* manager, const boost::shared_ptr<SipEndpointFactory>& factory,
+            const std::string& routingId, const LocatorRegistrySmartPrx& registry) : 
         mGroup(new SipGeneralGroup),
 	mPJSipManager(manager), 
         mEndpointFactory(factory), 
@@ -829,8 +735,7 @@ public:
     /**
      * A simplified version for the general group.
      */
-    void selectInto(const ConfigurationItemDict& requestedItems,
-            ConfigurationItemDict& returnedItems)
+    void selectInto(const ConfigurationItemDict& requestedItems, ConfigurationItemDict& returnedItems)
     {
         boost::shared_lock<boost::shared_mutex> lock(mLock);
         selectIntoImpl(requestedItems, mGroup->configurationItems, returnedItems);
@@ -1077,8 +982,7 @@ private:
     //
     // Helper function that does the selection out of one dictionary into another.
     //
-    void selectIntoImpl(const ConfigurationItemDict& requestedItems,
-	    const ConfigurationItemDict& localItems,
+    void selectIntoImpl(const ConfigurationItemDict& requestedItems, const ConfigurationItemDict& localItems,
 	    ConfigurationItemDict& returnedItems)
     {
         for (ConfigurationItemDict::const_iterator requestedItem = requestedItems.begin();
@@ -1213,10 +1117,8 @@ typedef boost::shared_ptr<ConfigurationData> ConfigurationDataPtr;
 class ConfigurationServiceImpl : public AsteriskSCF::System::Configuration::V1::ConfigurationService
 {
 public:
-    ConfigurationServiceImpl(PJSipManager* manager, 
-        const boost::shared_ptr<SipEndpointFactory>& endpointFactory, 
-        const std::string& routingId,
-	const LocatorRegistrySmartPrx& locatorProxy);
+    ConfigurationServiceImpl(PJSipManager* manager, const boost::shared_ptr<SipEndpointFactory>& endpointFactory, 
+        const std::string& routingId, const LocatorRegistrySmartPrx& locatorProxy);
     ConfigurationGroupSeq getConfiguration(const ConfigurationGroupSeq&, const Ice::Current&);
     ConfigurationGroupSeq getConfigurationAll(const ConfigurationGroupSeq&, const Ice::Current&);
     ConfigurationGroupSeq getConfigurationGroups(const Ice::Current&);
@@ -1242,10 +1144,9 @@ private:
 
 typedef IceUtil::Handle<ConfigurationServiceImpl> ConfigurationServiceImplPtr;
 
-ConfigurationServiceImpl::ConfigurationServiceImpl(PJSipManager* manager, 
-    const boost::shared_ptr<SipEndpointFactory>& factory,
-    const std::string& routingId, 
-    const LocatorRegistrySmartPrx& registry) :
+ConfigurationServiceImpl::ConfigurationServiceImpl(PJSipManager* manager,
+        const boost::shared_ptr<SipEndpointFactory>& factory, const std::string& routingId,
+        const LocatorRegistrySmartPrx& registry) :
     mData(new ConfigurationData(manager, factory, routingId, registry))
 {
 }
@@ -1277,8 +1178,7 @@ ConfigurationGroupSeq ConfigurationServiceImpl::getConfiguration(
 	/**
 	 * Internal helper function which determines what configuration items should be returned
 	 */
-	void insertRequestedConfigurationItems(ConfigurationItemDict& requestedItems,
-	    ConfigurationItemDict& localItems,
+	void insertRequestedConfigurationItems(ConfigurationItemDict& requestedItems, ConfigurationItemDict& localItems,
 	    ConfigurationItemDict& returnedItems)
 	{
 	    for (ConfigurationItemDict::iterator requestedItem = requestedItems.begin();
@@ -1347,8 +1247,8 @@ static void genericGetAll(const ConfigurationDataPtr& config, const T& group, Co
     }
 }
 
-ConfigurationGroupSeq ConfigurationServiceImpl::getConfigurationAll(const AsteriskSCF::System::Configuration::V1::ConfigurationGroupSeq& groups,
-        const Ice::Current&)
+ConfigurationGroupSeq ConfigurationServiceImpl::getConfigurationAll(
+    const AsteriskSCF::System::Configuration::V1::ConfigurationGroupSeq& groups, const Ice::Current&)
 {
     class Visitor : public SipConfigurationGroupVisitor
     {
@@ -1428,7 +1328,8 @@ static void genericSet(const ConfigurationDataPtr& config, const T& group)
     }
 }
 
-void ConfigurationServiceImpl::setConfiguration(const AsteriskSCF::System::Configuration::V1::ConfigurationGroupSeq& groups, const Ice::Current&)
+void ConfigurationServiceImpl::setConfiguration(const AsteriskSCF::System::Configuration::V1::ConfigurationGroupSeq& groups,
+        const Ice::Current&)
 {
     class GroupsVisitor : public SipConfigurationGroupVisitor
     {
@@ -1481,8 +1382,8 @@ void ConfigurationServiceImpl::setConfiguration(const AsteriskSCF::System::Confi
     }
 }
 
-void ConfigurationServiceImpl::removeConfigurationItems(const AsteriskSCF::System::Configuration::V1::ConfigurationGroupSeq& groups,
-        const Ice::Current&)
+void ConfigurationServiceImpl::removeConfigurationItems(
+    const AsteriskSCF::System::Configuration::V1::ConfigurationGroupSeq& groups, const Ice::Current&)
 {
     class GroupsVisitor : public SipConfigurationGroupVisitor
     {
@@ -1533,8 +1434,8 @@ void ConfigurationServiceImpl::removeConfigurationItems(const AsteriskSCF::Syste
     }
 }
 
-void ConfigurationServiceImpl::removeConfigurationGroups(const AsteriskSCF::System::Configuration::V1::ConfigurationGroupSeq& groups,
-        const Ice::Current&)
+void ConfigurationServiceImpl::removeConfigurationGroups(
+    const AsteriskSCF::System::Configuration::V1::ConfigurationGroupSeq& groups, const Ice::Current&)
 {
     class Visitor : public SipConfigurationGroupVisitor
     {

commit 53eea482a563ce1e74f78c7c1af1df61e82faad4
Author: Brent Eagles <beagles at digium.com>
Date:   Wed May 11 16:10:45 2011 -0230

    Trying out a command list approach to visitors.

diff --git a/src/SipConfiguration.cpp b/src/SipConfiguration.cpp
index fe70c56..a5d2cd3 100644
--- a/src/SipConfiguration.cpp
+++ b/src/SipConfiguration.cpp
@@ -18,6 +18,8 @@
 
 #include <boost/thread.hpp>
 #include <boost/shared_ptr.hpp>
+#include <boost/function.hpp>
+#include <boost/bind.hpp>
 
 #include <pjlib.h>
 #include <pjsip.h>
@@ -28,6 +30,7 @@
 #include "PJSipManager.h"
 #include "SipEndpointFactory.h"
 #include "SipConfiguration.h"
+#include <vector>
 
 using namespace AsteriskSCF::SIP::V1;
 using namespace AsteriskSCF::System::Configuration::V1;
@@ -51,30 +54,36 @@ namespace SipSessionManager
  *
  **/
 
-//
-// A generic instance of the createGroupTemplate() that creates a new, empty instance of a named group.
-//
-template <class T>
+/**
+ *
+ * A generic instance of the createGroupTemplate() that creates a new, empty instance of a named group.
+ *
+ * @param group an instance of the group to create a template for.
+ *
+ * @return a new instance of type T that may contain members copied from the group parameter.
+ *
+ **/
+template <typename T>
 T createGroupTemplate(const T& group)
 {
-    T result = new T::element_type;
+    T result = new typename T::element_type;
     assert(result);
     result->name = group->name;
     return result;
 }
 
-//
-// A specialization for SipGeneralGroup, which contains no additional members.
-//
+/**
+ * A specialization for SipGeneralGroup, which contains no additional members.
+ **/
 template<>
 SipGeneralGroupPtr createGroupTemplate(const SipGeneralGroupPtr&)
 {
     return new SipGeneralGroup;
 }
 
-//
-// Specialization required for SipDomainGroup for different members.
-//
+/**
+ * A specialization for SipDomainGroup which has a data member with a different name.
+ **/
 template <>
 SipDomainGroupPtr createGroupTemplate(const SipDomainGroupPtr& source)
 {
@@ -83,10 +92,16 @@ SipDomainGroupPtr createGroupTemplate(const SipDomainGroupPtr& source)
     return r;
 }
 
-//
-// Checks to see if an update is out of order and currently ... does nothing. We need to add some logging or
-// update filtering.
-//
+/**
+ *
+ * performSerialCheck checks to see if an update is out of order and currently ... does nothing. We need to add some
+ * logging or update filtering.
+ *
+ * @param changedItems the items in the update.
+ *
+ * @param localItems the current items in the configuration.
+ * 
+ **/
 static void performSerialCheck(const ConfigurationItemDict& changedItems, const ConfigurationItemDict& localItems)
 {
     for (ConfigurationItemDict::const_iterator item = changedItems.begin();
@@ -116,10 +131,13 @@ static void performSerialCheck(const ConfigurationItemDict& changedItems, const
     }
 }
 
-//
-// A helper class and visitor for propogating configuration changes to the SIPEndPoint implementation.
-//
-class EndpointConfigHelper
+typedef boost::function<void()> UpdateCommand;
+typedef vector<UpdateCommand> UpdateCommandList;
+
+/**
+ * A helper class and visitor for propogating configuration changes to the SIPEndPoint implementation.
+ **/
+class EndpointConfigHelper : public boost::enable_shared_from_this<EndpointConfigHelper>
 {
     //
     // Helper visitor that will be used to interpret the contents of the relevant configuration group.
@@ -143,7 +161,7 @@ class EndpointConfigHelper
                 // Don't forget to tell the helper that all of the updates have been performed
                 // and it can perform final processing.
                 //
-                mConfig->updated();
+                mConfig->updated(mUpdates);
             }
             catch(...)
             {
@@ -158,28 +176,30 @@ class EndpointConfigHelper
             }
         }
 
-        //
-        // Map visits to overloaded methods. Strictly speaking this isn't necessary as the helper
-        // could have implemented these methods itself. This is more for consistency and illustration
-        // than anything else and shows how an visitor implementation could "glue" the visitor code
-        // to a non-visitor implementation with total disregard to function signatures etc..
-        //
+        /**
+         * A different sort of approach to collecting the updates. By using boost's bind and function
+         * templates we can store the calls that we need to make and pass it to the configuration
+         * object's instance to call on itself. This allows the lock to only be held in once place,
+         * but the updates to appear to be spread over multiple calls.
+         **/
         void visitSipAllowableCallDirectionItem(const SipAllowableCallDirectionItemPtr& direction)
         {
-            mConfig->update(direction);
+            mUpdates.push_back(boost::bind(&EndpointConfigHelper::updateDirection, mConfig, direction));
         }
-
+        
         void visitSipSourceTransportAddressItem(const SipSourceTransportAddressItemPtr& source)
         {
-            mConfig->update(source);
+            mUpdates.push_back(boost::bind(&EndpointConfigHelper::updateSource, mConfig, source));
         }
 
         void visitSipTargetDestinationAddressItem(const SipTargetDestinationAddressItemPtr& target)
         {
-            mConfig->update(target);
+            mUpdates.push_back(boost::bind(&EndpointConfigHelper::updateTarget, mConfig, target));
         };
 
     private:
+
+        UpdateCommandList mUpdates;;
         //
         // We keep a reference to the parent as the helper itself isn't held by the configuration
         // object or client.
@@ -208,12 +228,11 @@ public:
 
     SipConfigurationItemVisitorPtr getVisitor()
     {
-        return new Visitor(boost::shared_ptr<EndpointConfigHelper>(this));
+        return new Visitor(shared_from_this());
     }
 
-    void update(const SipAllowableCallDirectionItemPtr& direction)
+    void updateDirection(const SipAllowableCallDirectionItemPtr& direction)
     {
-        boost::unique_lock<boost::shared_mutex> lock(mLock);
         enum Direction callDirection;
         switch (direction->callDirection)
         {
@@ -232,25 +251,36 @@ public:
         mEndpoint->setCallDirection(callDirection);
     }
 
-    void update(const SipSourceTransportAddressItemPtr& source)
+    void updateSource(const SipSourceTransportAddressItemPtr& source)
     {
-        boost::unique_lock<boost::shared_mutex> lock(mLock);
         mEndpoint->setSourceAddress(source->host, source->port);
     }
 
-    void update(const SipTargetDestinationAddressItemPtr& target)
+    void updateTarget(const SipTargetDestinationAddressItemPtr& target)
     {
-        boost::unique_lock<boost::shared_mutex> lock(mLock);
         mEndpoint->setTargetAddress(target->host, target->port);
     }
 
-    void updated()
+    void updated(const UpdateCommandList& updates)
     {
         //
-        // TODO: What about exception handling here... we probably don't want it
+        // NOTE: there is room for an inconsistent update, but holding the lock
+        // during RPCs seems like a bad plan. Even calling mFactory from
+        // here is a little suspect.
         //
         RegExSeq destinations;
-        mFactory->generateRoutingDestinations(destinations);
+        {
+            boost::unique_lock<boost::shared_mutex> lock(mLock);
+            for (UpdateCommandList::const_iterator op = updates.begin();
+                 op != updates.end();
+                 ++op)
+            {
+                UpdateCommand command = *op;
+                command();
+            }
+            mFactory->generateRoutingDestinations(destinations);
+        }
+        
         mRegistry->setEndpointLocatorDestinationIds(mRoutingId, destinations);
     }
 
@@ -275,12 +305,12 @@ public:
 };
 typedef boost::shared_ptr<ConfigBase> ConfigBasePtr;
 
-//
-// The Transport specializations take care of any transport specific configuration and
-// initialization. The UDP and TCP transports are so similar that they could probably
-// share some functionality.
-//
-class UDPTransportConfig : public ConfigBase
+/**
+ * The Transport specializations take care of any transport specific configuration and
+ * initialization. The UDP and TCP transports are so similar that they could probably
+ * share some functionality.
+ **/
+class UDPTransportConfig : public ConfigBase, public boost::enable_shared_from_this<UDPTransportConfig>
 {
     class Visitor : public SipConfigurationItemVisitor
     {
@@ -337,7 +367,8 @@ public:
 
     SipConfigurationItemVisitorPtr getVisitor()
     {
-        return new Visitor(boost::shared_ptr<UDPTransportConfig>(this));
+        
+        return new Visitor(shared_from_this());
     }
 
     void update(const SipHostItemPtr& hostItem)
@@ -392,6 +423,7 @@ public:
     }
 private:
     boost::shared_mutex mLock;
+    SipConfigurationItemVisitorPtr mCurrentVisitor;
 
     /**
      * Address itself.
@@ -420,7 +452,7 @@ private:
 typedef boost::shared_ptr<UDPTransportConfig> UDPTransportConfigPtr;
 typedef std::map<std::string, UDPTransportConfigPtr> UDPTransportMap;
 
-class TCPTransportConfig : public ConfigBase
+class TCPTransportConfig : public ConfigBase, public boost::enable_shared_from_this<TCPTransportConfig>
 {
     class Visitor : public SipConfigurationItemVisitor
     {
@@ -477,7 +509,7 @@ public:
     
     SipConfigurationItemVisitorPtr getVisitor()
     {
-        return new Visitor(boost::shared_ptr<TCPTransportConfig>(this));
+        return new Visitor(shared_from_this());
     }
 
     void update(const SipHostItemPtr& hostItem)
@@ -561,7 +593,7 @@ private:
 typedef boost::shared_ptr<TCPTransportConfig> TCPTransportConfigPtr;
 typedef std::map<std::string, TCPTransportConfigPtr> TCPTransportMap;
 
-class TLSTransportConfig : public ConfigBase
+class TLSTransportConfig : public ConfigBase, public boost::enable_shared_from_this<TLSTransportConfig>
 {
     class Visitor : public SipConfigurationItemVisitor
     {
@@ -634,7 +666,7 @@ public:
 
     SipConfigurationItemVisitorPtr getVisitor()
     {
-        return new Visitor(boost::shared_ptr<TLSTransportConfig>(this));
+        return new Visitor(shared_from_this());
     }
 
     void update(const SipHostItemPtr& hostItem)
@@ -667,9 +699,9 @@ public:
     {
         boost::unique_lock<boost::shared_mutex> lock(mLock);
         mNeedsUpdating = true;
-        mTLSSettings.verify_server = (requirements->requireVerifiedServer == false) ? PJ_FALSE : PJ_TRUE;
-        mTLSSettings.verify_client = (requirements->requireVerifiedClient == false) ? PJ_FALSE : PJ_TRUE;
-        mTLSSettings.require_client_cert = (requirements->requireClientCertificate == false) ? PJ_FALSE : PJ_TRUE;
+        mTLSSettings.verify_server = (requirements->requireVerifiedServer) ? PJ_TRUE : PJ_FALSE;
+        mTLSSettings.verify_client = (requirements->requireVerifiedClient) ? PJ_TRUE : PJ_FALSE;
+        mTLSSettings.require_client_cert = (requirements->requireClientCertificate) ? PJ_TRUE : PJ_FALSE;
     }
 
     void update(const SipCryptoItemPtr& crypto)
@@ -768,13 +800,13 @@ bool getItem(const C& collection, I& iter, const K& key)
     return iter != collection.end();
 }
 
-//
-// ConfigurationData goes into a class by itself to aide in sharing and locking. Operations on the configuration data
-// have been heavily generalized into templates and type specific helpers that map the protocols described by the
-// template members to type specific instantiations. The general premise is to remove/reduce repeated code
-// and keep it restricted the most specialized uses possible. There are definitely a few more things that
-// could be done.
-//
+/**
+ * ConfigurationData goes into a class by itself to aide in sharing and locking. Operations on the configuration data
+ * have been heavily generalized into templates and type specific helpers that map the protocols described by the
+ * template members to type specific instantiations. The general premise is to remove/reduce repeated code
+ * and keep it restricted the most specialized uses possible. There are definitely a few more things that
+ * could be done.
+ **/
 class ConfigurationData
 {
 public:
@@ -866,9 +898,8 @@ public:
     void remove(const SipUDPTransportGroupPtr& group)
     {
         //
-        // It's a good idea to hold a reference to this until after we release the lock
-        // on the config item. That way any code that might happen as a result of
-        // its destruction cannot come back and cause deadlocks on this object.
+        // It's a good idea to hold a reference to this until after we release the lock on the config item. That way any
+        // code that might happen as a result of its destruction cannot come back and cause deadlocks on this object.
         //
         UDPTransportConfigPtr config;
         {
@@ -885,9 +916,8 @@ public:
     void remove(const SipTCPTransportGroupPtr& group)
     {
         //
-        // It's a good idea to hold a reference to this until after we release the lock
-        // on the config item. That way any code that might happen as a result of
-        // its destruction cannot come back and cause deadlocks on this object.
+        // It's a good idea to hold a reference to this until after we release the lock on the config item. That way any
+        // code that might happen as a result of its destruction cannot come back and cause deadlocks on this object.
         //
         TCPTransportConfigPtr config;
         {
@@ -904,9 +934,8 @@ public:
     void remove(const SipTLSTransportGroupPtr& group)
     {
         //
-        // It's a good idea to hold a reference to this until after we release the lock
-        // on the config item. That way any code that might happen as a result of
-        // its destruction cannot come back and cause deadlocks on this object.
+        // It's a good idea to hold a reference to this until after we release the lock on the config item. That way any
+        // code that might happen as a result of its destruction cannot come back and cause deadlocks on this object.
         //
         TLSTransportConfigPtr config;
         {
@@ -936,12 +965,11 @@ public:
         copyTemplates(groups, mEndpoints);
     }
 
-    //
-    // The following getItemsFor() members basically do a data member selection by type.
-    // Interestingly, this is simply an extension of the idea behind the visitor extension
-    // to Ice, but it takes it further, allowing a large degree of generalization in
-    // a shared data class.
-    //
+    /**
+     * The following getItemsFor() members basically do a data member selection by type.  Interestingly, this is simply
+     * an extension of the idea behind the visitor extension to Ice, but it takes it further, allowing a large degree of
+     * generalization in a shared data class.
+     **/
     const SipDomainGroupPtr getGroupFor(const SipDomainGroupPtr& group)
     {
         DomainMap::const_iterator i;

commit 9713fcc350ecc28c95ee74154806e8a36033cdc4
Author: Brent Eagles <beagles at digium.com>
Date:   Wed May 11 14:21:14 2011 -0230

    Responding to review feedback.

diff --git a/src/SipConfiguration.cpp b/src/SipConfiguration.cpp
index e60dc74..6a55060 100644
--- a/src/SipConfiguration.cpp
+++ b/src/SipConfiguration.cpp
@@ -59,7 +59,7 @@ SipGeneralGroupPtr createGroupTemplate(const SipGeneralGroupPtr&)
     return new SipGeneralGroup;
 }
 
-//
+/**
 // Specialization require since the name is different.
 //
 template <>
@@ -99,7 +99,7 @@ static void performSerialCheck(const ConfigurationItemDict& changedItems, const
     }
 }
 
-class EndpointConfigHelper
+class EndpointConfigHelper : public boost::enable_shared_from_this<EndpointConfigHelper>
 {
     class Visitor : public SipConfigurationItemVisitor
     {
@@ -154,7 +154,7 @@ public:
 
     SipConfigurationItemVisitorPtr getVisitor()
     {
-        return new Visitor(boost::shared_ptr<EndpointConfigHelper>(this));
+        return new Visitor(shared_from_this());
     }
 
     void update(const SipAllowableCallDirectionItemPtr& direction)
@@ -218,7 +218,7 @@ public:
 };
 typedef boost::shared_ptr<ConfigBase> ConfigBasePtr;
     
-class UDPTransportConfig : public ConfigBase
+class UDPTransportConfig : public ConfigBase, public boost::enable_shared_from_this<UDPTransportConfig>
 {
     class Visitor : public SipConfigurationItemVisitor
     {
@@ -266,7 +266,7 @@ public:
 
     SipConfigurationItemVisitorPtr getVisitor()
     {
-        return new Visitor(boost::shared_ptr<UDPTransportConfig>(this));
+        return new Visitor(shared_from_this());
     }
 
     void update(const SipHostItemPtr& hostItem)
@@ -349,7 +349,7 @@ private:
 typedef boost::shared_ptr<UDPTransportConfig> UDPTransportConfigPtr;
 typedef std::map<std::string, UDPTransportConfigPtr> UDPTransportMap;
 
-class TCPTransportConfig : public ConfigBase
+class TCPTransportConfig : public ConfigBase, public boost::enable_shared_from_this<TCPTransportConfig>
 {
     class Visitor : public SipConfigurationItemVisitor
     {
@@ -397,7 +397,7 @@ public:
     
     SipConfigurationItemVisitorPtr getVisitor()
     {
-        return new Visitor(boost::shared_ptr<TCPTransportConfig>(this));
+        return new Visitor(shared_from_this());
     }
 
     void update(const SipHostItemPtr& hostItem)
@@ -481,7 +481,7 @@ private:
 typedef boost::shared_ptr<TCPTransportConfig> TCPTransportConfigPtr;
 typedef std::map<std::string, TCPTransportConfigPtr> TCPTransportMap;
 
-class TLSTransportConfig : public ConfigBase
+class TLSTransportConfig : public ConfigBase, public boost::enable_shared_from_this<TLSTransportConfig>
 {
     class Visitor : public SipConfigurationItemVisitor
     {
@@ -545,7 +545,7 @@ public:
 
     SipConfigurationItemVisitorPtr getVisitor()
     {
-        return new Visitor(boost::shared_ptr<TLSTransportConfig>(this));
+        return new Visitor(shared_from_this());
     }
 
     void update(const SipHostItemPtr& hostItem)
@@ -578,9 +578,9 @@ public:
     {
         boost::unique_lock<boost::shared_mutex> lock(mLock);
         mNeedsUpdating = true;
-        mTLSSettings.verify_server = (requirements->requireVerifiedServer == false) ? PJ_FALSE : PJ_TRUE;
-        mTLSSettings.verify_client = (requirements->requireVerifiedClient == false) ? PJ_FALSE : PJ_TRUE;
-        mTLSSettings.require_client_cert = (requirements->requireClientCertificate == false) ? PJ_FALSE : PJ_TRUE;
+        mTLSSettings.verify_server = (requirements->requireVerifiedServer) ? PJ_TRUE : PJ_FALSE;
+        mTLSSettings.verify_client = (requirements->requireVerifiedClient) ? PJ_TRUE : PJ_FALSE;
+        mTLSSettings.require_client_cert = (requirements->requireClientCertificatee) ? PJ_TRUE : PJ_FALSE;
     }
 
     void update(const SipCryptoItemPtr& crypto)

-----------------------------------------------------------------------


-- 
asterisk-scf/integration/sip.git



More information about the asterisk-scf-commits mailing list