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

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Wed Mar 28 10:57:02 CDT 2012


branch "retry_deux" has been updated
       via  71eeab06a117530626725bab0c43c5835ffe600c (commit)
       via  08af19f9bfb706348f5d03ee569ce10c206780c0 (commit)
       via  7207e3ad1c6587173441bd94e05c25f5397156b5 (commit)
       via  aa883ce019d88df3a9b50f2df78370ea6c8837c1 (commit)
       via  931b37bca7117716f7f6742d70ddeab0d3122f2b (commit)
       via  9bf9bf8fa1d3b95496a6c7571db5b9deda19bad7 (commit)
       via  17b8c4b31831b58c48bab18d96d07023f29ca33d (commit)
       via  dd69b74a39e35efd82b59087c3f69224ccee531e (commit)
      from  1843243fcdc029e058cacccd1e50ba1c7d03787a (commit)

Summary of changes:
 config/Sip.config                      |   38 ++++
 config/SipConfigurator.py              |   87 ++++++++--
 src/CMakeLists.txt                     |    3 +-
 src/Component.cpp                      |   18 ++-
 src/ComponentStateReplicator.cpp       |  108 +++++++++++
 src/PJSIPManager.cpp                   |    5 +
 src/PJSIPManager.h                     |    9 +
 src/PJSIPSessionModule.cpp             |   95 ++++++++++-
 src/PJSIPSessionModule.h               |   13 ++
 src/PJSIPSessionModuleConstruction.cpp |   14 ++-
 src/SIPConfiguration.cpp               |   92 +++++++++-
 src/SIPEndpoint.cpp                    |   15 ++
 src/SIPEndpoint.h                      |   21 ++
 src/SIPSession.cpp                     |   33 +++-
 src/SIPStateReplicatorApp.cpp          |  316 --------------------------------
 src/STUNModule.cpp                     |   16 ++-
 16 files changed, 528 insertions(+), 355 deletions(-)
 create mode 100644 src/ComponentStateReplicator.cpp
 delete mode 100644 src/SIPStateReplicatorApp.cpp


- Log -----------------------------------------------------------------
commit 71eeab06a117530626725bab0c43c5835ffe600c
Merge: 08af19f 1843243
Author: Ken Hunt <ken.hunt at digium.com>
Date:   Tue Mar 27 19:02:50 2012 -0500

    Merge of the replication updates.


commit 08af19f9bfb706348f5d03ee569ce10c206780c0
Merge: 7207e3a 2dd1870
Author: Ken Hunt <ken.hunt at digium.com>
Date:   Mon Mar 26 16:09:28 2012 -0500

    Merge branch 'retry_deux' of git.asterisk.org:asterisk-scf/integration/sip into retry_deux

diff --cc src/SIPConfiguration.cpp
index 7f133a0,5204d53..31ebf66
--- a/src/SIPConfiguration.cpp
+++ b/src/SIPConfiguration.cpp
@@@ -37,20 -36,17 +37,23 @@@
  #include "TLSTransport.h"
  #include "STUNTransportConfig.h"
  #include <vector>
- #include <AsteriskSCF/Helpers/Network.h>
+ #include <AsteriskSCF/Operations/OperationContext.h>
+ #include <AsteriskSCF/Operations/OperationContextCache.h>
  
 +using namespace AsteriskSCF::System::Logging;
  using namespace AsteriskSCF::System::Configuration::V1;
  using namespace AsteriskSCF::Configuration::SIPSessionManager::V1;
  using namespace AsteriskSCF::SessionCommunications::PartyIdentification::V1;
  using namespace AsteriskSCF::Core::Routing::V1;
+ using namespace AsteriskSCF::System::V1;
+ using namespace AsteriskSCF::Operations;
  using namespace std;
  
 +namespace
 +{
 +Logger lg = getLoggerFactory().getLogger("AsteriskSCF.SIPSessionGateway");
 +}
 +
  //
  // Note: the general group receives a default value in this refactoring no matter what, I suspect that this is actually
  // wrong and will address.
@@@ -1945,11 -1866,18 +1950,20 @@@ static void runPostProcessing(
      }
  }
  
- void ConfigurationServiceImpl::setConfiguration(const AsteriskSCF::System::Configuration::V1::ConfigurationGroupSeq& groups,
-         const Ice::Current&)
+ void ConfigurationServiceImpl::setConfiguration(
+     const OperationContextPtr& operationContext, 
+     const AsteriskSCF::System::Configuration::V1::ConfigurationGroupSeq& groups,
+     const Ice::Current&)
  {
 +    lg(Debug) << "Configuration: setting configuration data.";
 +
+     // Is this a retry for an operation we're already processing?
+     if (!mOperationContextCache->addOperationContext(operationContext))
+     {
+         // It's not quite this simple. But for now, ...
+         return;
+     }
+ 
      class GroupsVisitor : public SIPConfigurationGroupVisitor
      {
      public:
diff --cc src/SIPSession.cpp
index a8d7169,96658f1..982a390
--- a/src/SIPSession.cpp
+++ b/src/SIPSession.cpp
@@@ -3610,12 -3750,8 +3761,12 @@@ pjmedia_sdp_session *SIPSession::create
                  {
                      options->handleTelephonyEvents = true;
                  }
 +                if (!config.sessionConfig.mediaServiceName.empty())
 +                {
 +                    params->service = config.sessionConfig.mediaServiceName;
 +                }
  
-                 session = factory->allocate(params, options, outputs);
+                 session = factory->allocate(operationContext, params, options, outputs);
  
                  // Double check to make sure they actually gave us a sesson back... they could have had a problem
                  if (session == 0)

commit 7207e3ad1c6587173441bd94e05c25f5397156b5
Author: Ken Hunt <ken.hunt at digium.com>
Date:   Fri Feb 10 11:37:46 2012 -0600

    Changes to base class ComponentStateReplicator and some logging during configuration.

diff --git a/src/ComponentStateReplicator.cpp b/src/ComponentStateReplicator.cpp
index 34446c6..d2f6383 100644
--- a/src/ComponentStateReplicator.cpp
+++ b/src/ComponentStateReplicator.cpp
@@ -45,7 +45,8 @@ public:
     ComponentStateReplicator() :
       AsteriskSCF::Component::ComponentStateReplicator(lg, 
           AsteriskSCF::Replication::SIPSessionManager::V1::StateReplicatorComponentCategory, 
-          true) // if true, supports configuration
+          true,                               // if true, supports configuration
+          AsteriskSCF::Configuration::SIPSessionManager::V1::ConfigurationDiscoveryCategory) 
     {
     }
 
diff --git a/src/SIPConfiguration.cpp b/src/SIPConfiguration.cpp
index 484d7a2..7f133a0 100644
--- a/src/SIPConfiguration.cpp
+++ b/src/SIPConfiguration.cpp
@@ -25,6 +25,7 @@
 #include <boost/bind.hpp>
 
 #include <AsteriskSCF/System/Component/ConfigurationIf.h>
+#include <AsteriskSCF/Logger.h>
 
 #include "SIPConfigurationIf.h"
 #include "PJSIPManager.h"
@@ -38,12 +39,18 @@
 #include <vector>
 #include <AsteriskSCF/Helpers/Network.h>
 
+using namespace AsteriskSCF::System::Logging;
 using namespace AsteriskSCF::System::Configuration::V1;
 using namespace AsteriskSCF::Configuration::SIPSessionManager::V1;
 using namespace AsteriskSCF::SessionCommunications::PartyIdentification::V1;
 using namespace AsteriskSCF::Core::Routing::V1;
 using namespace std;
 
+namespace
+{
+Logger lg = getLoggerFactory().getLogger("AsteriskSCF.SIPSessionGateway");
+}
+
 //
 // Note: the general group receives a default value in this refactoring no matter what, I suspect that this is actually
 // wrong and will address.
@@ -1552,6 +1559,7 @@ private:
         if (!endpoint)
         {
 	    endpoint = mEndpointFactory->createEndpoint(group->name);
+            lg(Debug) << "Configuration: Added endpoint " << group->name;
         }
         return boost::shared_ptr<EndpointConfigHelper>(
             new EndpointConfigHelper(endpoint, mEndpointFactory, mRoutingServiceLocatorRegistry, mRoutingId))->getVisitor();
@@ -1940,6 +1948,8 @@ static void runPostProcessing()
 void ConfigurationServiceImpl::setConfiguration(const AsteriskSCF::System::Configuration::V1::ConfigurationGroupSeq& groups,
         const Ice::Current&)
 {
+    lg(Debug) << "Configuration: setting configuration data.";
+
     class GroupsVisitor : public SIPConfigurationGroupVisitor
     {
     public:

commit aa883ce019d88df3a9b50f2df78370ea6c8837c1
Author: Brent Eagles <beagles at digium.com>
Date:   Wed Feb 8 11:35:38 2012 -0330

    Squashed commit of branch jira-astscf-397-sipuseragent. Integrates the
    following changes:
    
    - Added a check to make sure that the smart proxy for the session router is
      only overridden if the configured and default values differ.
    
    - Changes to incorporate user agent header setting, propagate different media
      service name configurations as well as the routing service configuration
      name. The latter involved adding an override in the PJSSIPSessionModule
      prior to call begin_routeSession().
    
    - Added support for configuration of the "User-Agent" general configuration item.

diff --git a/config/SipConfigurator.py b/config/SipConfigurator.py
index 4ba6cd7..f90a005 100755
--- a/config/SipConfigurator.py
+++ b/config/SipConfigurator.py
@@ -37,6 +37,14 @@ class SIPSectionVisitors(Configurator.SectionVisitors):
     def visit_general(self, config, section):
         group = AsteriskSCF.Configuration.SIPSessionManager.V1.SIPGeneralGroup()
         group.configurationItems = { }
+        mapper = Configurator.OptionMapper()
+        item = AsteriskSCF.Configuration.SipSessionManager.V1.SipUserAgentItem()
+        mapper.map('useragent', item, 'userAgent', 'userAgent', config.get, None)
+        for option in config.options(section):
+            mapper.execute(group, section, option)
+
+        mapper.finish(group)
+        
         self.groups.append(group)
 
     def visit_transport_udp(self, config, section):
@@ -298,6 +306,7 @@ class SIPSectionVisitors(Configurator.SectionVisitors):
 
         item = AsteriskSCF.Configuration.SIPSessionManager.V1.SIPRTPMediaServiceItem()
         mapper.map('rtpoveripv6', item, 'requireIPv6', 'mediaservice', config.getboolean, None)
+        mapper.map('rtpmediaservice', item, 'mediaServiceName', 'mediaservice', config.get, None)
 
         item = AsteriskSCF.Configuration.SIPSessionManager.V1.DirectMediaItem()
         mapper.map('directmedia', item, 'enabled', 'directmedia', config.getboolean, None)
@@ -306,6 +315,7 @@ class SIPSectionVisitors(Configurator.SectionVisitors):
         mapper.map('udptloveripv6', item, 'requireIPv6', 'udptlmediaservice', config.getboolean, None)
         mapper.map('udptloverice', item, 'enableICE', 'udptlmediaservice', config.getboolean, None)
         mapper.map('udptlwithturn', item, 'enableTURN', 'udptlmediaservice', config.getboolean, None)
+        mapper.map('udptlmediaservice', item, 'mediaServiceName', 'udptlmediaservice', config.get, None);
 
         item = AsteriskSCF.Configuration.SIPSessionManager.V1.SIPCryptoCertificateItem()
         mapper.map('certificateauthorityfile', item, 'certificateAuthority', 'cryptocert', config.get, None)
diff --git a/src/PJSIPManager.cpp b/src/PJSIPManager.cpp
index b8d3f45..d706c29 100644
--- a/src/PJSIPManager.cpp
+++ b/src/PJSIPManager.cpp
@@ -251,6 +251,11 @@ void PJSIPManager::handleEvents()
     pjsip_endpt_handle_events(mEndpoint, &delay);
 }
 
+void PJSIPManager::setUserAgent(const string& userAgent)
+{
+    mSessionModule->setUserAgent(userAgent);
+}
+
 pj_caching_pool* PJSIPManager::getCachingPool()
 {
     return &mCachingPool;
diff --git a/src/PJSIPManager.h b/src/PJSIPManager.h
index f718ae7..ca10ca6 100644
--- a/src/PJSIPManager.h
+++ b/src/PJSIPManager.h
@@ -138,6 +138,15 @@ public:
 
     void handleEvents();
 
+    /**
+     * This would be better defined somewhere else, but at the moment
+     * configuration can't quite reach the PJSIPSessionModule definition
+     * While configuration could pull it in via include, it brings in a
+     * boat-load of extra build-time dependencies. The proper way to do
+     * this is to have a general configuration proxy class.
+     */
+    void setUserAgent(const std::string& userAgent);
+
 private:
     pjsip_endpoint *mEndpoint;
     PJSIPSessionModulePtr mSessionModule;
diff --git a/src/PJSIPSessionModule.cpp b/src/PJSIPSessionModule.cpp
index 79a58a5..12a0f08 100644
--- a/src/PJSIPSessionModule.cpp
+++ b/src/PJSIPSessionModule.cpp
@@ -409,6 +409,66 @@ protected:
             return Complete;
         }
 
+        AsteriskSCF::Discovery::SmartProxy<SessionRouterPrx> sessionRouter = mSessionRouter;
+
+        SIPEndpointConfig endpointConfig = mCaller->getConfig();
+        if (!endpointConfig.sessionConfig.routingServiceName.empty())
+        {
+            lg(Trace) << "overriding default session router";
+            try
+            {
+                AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr locationParameters =
+                    sessionRouter.getLocationParameters();
+                //
+                // Only change them if they are not equal.
+                //
+                if (locationParameters->service != endpointConfig.sessionConfig.routingServiceName)
+                {
+                    locationParameters->service = endpointConfig.sessionConfig.routingServiceName;
+                    //
+                    // This should throw a 'ServiceNotFound' et al. if it is bogus.
+                    //
+                    sessionRouter = AsteriskSCF::Discovery::SmartProxy<SessionRouterPrx>(
+                        sessionRouter.getLocator(), locationParameters, lg);
+                }
+            }
+            catch (const std::exception& ex)
+            {
+                lg(Error) << "Caught an " << ex.what() <<
+                    " while trying to locate configured session routing component: "
+                          << endpointConfig.sessionConfig.routingServiceName << ", responding with 500";
+                //
+                // Everything else doesn't really map so they just become internal server errors
+                //
+                if (success(pjsip_inv_end_session(mInv, 500, NULL, &mTdata)))
+                {
+                    pjsip_inv_send_msg(mInv, mTdata);
+                }
+                else
+                {
+                    lg(Warning) << "Unable to create 500 response for INVITE";
+                }
+            }
+            catch (...)
+            {
+                lg(Error) << "Caught an unknown exception " << 
+                    " while trying to locate configured session routing component: "
+                          << endpointConfig.sessionConfig.routingServiceName << ", responding with 500";
+                
+                //
+                // Everything else doesn't really map so they just become internal server errors
+                //
+                if (success(pjsip_inv_end_session(mInv, 500, NULL, &mTdata)))
+                {
+                    pjsip_inv_send_msg(mInv, mTdata);
+                }
+                else
+                {
+                    lg(Warning) << "Unable to create 500 response for INVITE";
+                }
+            }
+        }
+
         mSession->setInviteSession(mInv);
         mSession->setDialog(mInv->dlg);
 
@@ -480,7 +540,7 @@ protected:
                 SuspendableWorkListenerPtr listener = 0;
                 SIPAMICallbackPtr cb(new SIPAMICallback(listener, mSession, this, false, true));
                 Ice::CallbackPtr d = Ice::newCallback(cb, &SIPAMICallback::callback);
-                mSessionRouter->begin_routeSession(operationId, mSession->getSessionProxy(), mDestination, 0, mCallerID, mRedirections, d);
+                sessionRouter->begin_routeSession(operationId, mSession->getSessionProxy(), mDestination, 0, mCallerID, mRedirections, d);
             }
         }
         catch (const Ice::CommunicatorDestroyedException &)
@@ -823,6 +883,35 @@ ConnectedLinePtr PJSIPSessionModule::getConnectedID(pjsip_rx_data *rdata)
     return connected;
 }
 
+std::string PJSIPSessionModule::getUserAgent()
+{
+    boost::shared_lock<boost::shared_mutex> lock(mUserAgentMutex);
+    return mUserAgent;
+}
+
+void PJSIPSessionModule::setUserAgent(const std::string& userAgent)
+{
+    boost::unique_lock<boost::shared_mutex> lock(mUserAgentMutex);
+    mUserAgent = userAgent;
+}
+
+void PJSIPSessionModule::addDefaultHeaders(pjsip_tx_data *tx)
+{
+    std::string userAgent = getUserAgent();
+    if (userAgent.empty() || !tx)
+    {
+        return;
+    }
+
+    pj_str_t uaHeaderField;
+    pj_cstr(&uaHeaderField, "User-Agent");
+    pj_str_t uaHeaderValue;
+    pj_strset(&uaHeaderValue, (char*)userAgent.c_str(), userAgent.length());
+    pjsip_generic_string_hdr* hdr =
+        pjsip_generic_string_hdr_create(tx->pool, &uaHeaderField, &uaHeaderValue);
+    pjsip_msg_add_hdr(tx->msg, (pjsip_hdr*)hdr);
+}
+
 void PJSIPSessionModule::handleNewInvite(pjsip_rx_data *rdata)
 {
     //We handle most of the processing here synchronously since
@@ -1379,12 +1468,14 @@ pj_bool_t PJSIPSessionModule::on_rx_response(pjsip_rx_data*)
 {
     return PJ_FALSE;
 }
-pj_status_t PJSIPSessionModule::on_tx_request(pjsip_tx_data*)
+pj_status_t PJSIPSessionModule::on_tx_request(pjsip_tx_data* tx)
 {
+    addDefaultHeaders(tx);
     return PJ_SUCCESS;
 }
-pj_status_t PJSIPSessionModule::on_tx_response(pjsip_tx_data*)
+pj_status_t PJSIPSessionModule::on_tx_response(pjsip_tx_data* tx)
 {
+    addDefaultHeaders(tx);
     return PJ_SUCCESS;
 }
 void PJSIPSessionModule::on_tsx_state(pjsip_transaction*, pjsip_event*)
diff --git a/src/PJSIPSessionModule.h b/src/PJSIPSessionModule.h
index 7a6cbec..f9874ed 100644
--- a/src/PJSIPSessionModule.h
+++ b/src/PJSIPSessionModule.h
@@ -142,7 +142,13 @@ public:
 
     AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookSeq getSessionCreationHooks();
 
+    std::string getUserAgent();
+    void setUserAgent(const std::string& userAgent);
+
 private:
+
+    void addDefaultHeaders(pjsip_tx_data* tx);
+    
     void handleNewInvite(pjsip_rx_data *rdata);
 
     /**
@@ -237,6 +243,13 @@ private:
     AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationExtensionPointPrx mSessionCreationExtensionPointPrx;
     Ice::ObjectAdapterPtr mAdapter;
     AsteriskSCF::Core::Discovery::V1::ServiceManagementPrx mSessionCreationExtensionPointService;
+
+    //
+    // This is really the only thing that needs locking, so the mutex
+    // variable is named with that intent.
+    //
+    boost::shared_mutex mUserAgentMutex;
+    std::string mUserAgent;
 };
 
 typedef IceUtil::Handle<PJSIPSessionModule> PJSIPSessionModulePtr;
diff --git a/src/PJSIPSessionModuleConstruction.cpp b/src/PJSIPSessionModuleConstruction.cpp
index 002e09f..4fbfe8d 100644
--- a/src/PJSIPSessionModuleConstruction.cpp
+++ b/src/PJSIPSessionModuleConstruction.cpp
@@ -69,6 +69,16 @@ static pj_bool_t sessionOnRxRequest(pjsip_rx_data *rdata)
     return sessionModule->on_rx_request(rdata);
 }
 
+static pj_bool_t sessionOnTxRequest(pjsip_tx_data *tdata)
+{
+    return sessionModule->on_tx_request(tdata);
+}
+
+static pj_bool_t sessionOnTxResponse(pjsip_tx_data *tdata)
+{
+    return sessionModule->on_tx_response(tdata);
+}
+
 static void invOnStateChanged(pjsip_inv_session *inv, pjsip_event *e)
 {
     sessionModule->invOnStateChanged(inv, e);
@@ -140,8 +150,8 @@ PJSIPSessionModule::PJSIPSessionModule(pjsip_endpoint *endpt,
     mModule.unload = sessionUnload;
     mModule.on_rx_request = sessionOnRxRequest;
     mModule.on_rx_response = NULL;
-    mModule.on_tx_request = NULL;
-    mModule.on_tx_response = NULL;
+    mModule.on_tx_request = sessionOnTxRequest;
+    mModule.on_tx_response = sessionOnTxResponse;
     mModule.on_tsx_state = NULL;
 
     mSessionCreationExtensionPointPrx =
diff --git a/src/SIPConfiguration.cpp b/src/SIPConfiguration.cpp
index badd6b0..484d7a2 100644
--- a/src/SIPConfiguration.cpp
+++ b/src/SIPConfiguration.cpp
@@ -291,6 +291,69 @@ private:
 
 }; // class IdentityConfig
 
+class GeneralGroupConfig : public ConfigBase, public boost::enable_shared_from_this<GeneralGroupConfig>
+{
+    class Visitor : public SIPConfigurationItemVisitor
+    {
+    public:
+        Visitor(const boost::shared_ptr<GeneralGroupConfig>& config) :
+            mConfig(config)
+        {
+        }
+
+        ~Visitor()
+        {
+            mConfig->finish();
+        }
+
+        void visitSIPUserAgent(const SIPUserAgentItemPtr& userAgent)
+        {
+            mConfig->setUserAgentField(userAgent);
+        }
+
+    private:
+        boost::shared_ptr<GeneralGroupConfig> mConfig;
+    };
+public:
+    GeneralGroupConfig(const PJSIPManagerPtr& manager, const SIPGeneralGroupPtr& group):
+        mManager(manager),
+        mGroup(group)
+    {
+    }
+
+    void setUserAgentField(const SIPUserAgentItemPtr& userAgent)
+    {
+        boost::unique_lock<boost::shared_mutex> lock(mLock);
+        mUserAgent = userAgent;
+        mGroup->configurationItems["user-agent"] = userAgent;
+    }
+
+    void finish()
+    {
+        boost::shared_lock<boost::shared_mutex> lock(mLock);
+        if (mUserAgent)
+        {
+            mManager->setUserAgent(mUserAgent->userAgent);
+        }
+    }
+
+    SIPGeneralGroupPtr getTypedGroup() const
+    {
+        return mGroup;
+    }
+
+    SIPConfigurationItemVisitorPtr getVisitor()
+    {
+        return new Visitor(shared_from_this());
+    }
+
+private:
+    boost::shared_mutex mLock;
+    SIPUserAgentItemPtr mUserAgent;
+    SIPGeneralGroupPtr mGroup;
+    PJSIPManagerPtr mManager;
+};
+
 /**
  * A helper class and visitor for propogating configuration changes to the SIPEndPoint implementation.
  **/
@@ -527,11 +590,13 @@ public:
 
     void updateMediaService(const SIPRTPMediaServiceItemPtr& service)
     {
+        mEndpoint->setMediaServiceName(service->mediaServiceName);
 	mEndpoint->setRTPOverIPv6(service->requireIPv6);
     }
 
     void updateUDPTLMediaService(const SIPUDPTLMediaServiceItemPtr& service)
     {
+        mEndpoint->setUDPTLMediaServiceName(service->mediaServiceName);
         mEndpoint->setUDPTLOverIPv6(service->requireIPv6);
         mEndpoint->enableUDPTLICE(service->enableICE);
         mEndpoint->enableUDPTLTURN(service->enableTURN);
@@ -542,6 +607,11 @@ public:
 	mEndpoint->setSecureTransport(translateCallDirection(transport->secureTransport));
     }
 
+    void updateRouting(const SIPRoutingItemPtr& item)
+    {
+        mEndpoint->setRoutingServiceName(item->routingServiceName);
+    }
+
     void updateSRTP(const SRTPCryptoItemPtr& srtpOptions)
     {
         SIPEndpointMediaSRTPConfig srtpConfig(mEndpoint->getConfig().srtpConfig);
@@ -1139,7 +1209,7 @@ public:
         return updateGroup(v);
     }
 
-    void remove(const SIPGeneralGroupPtr&)
+    void remove(const SIPGeneralGroupPtr& group)
     {
         boost::unique_lock<boost::shared_mutex> lock(mLock);
         mGroup = 0;
@@ -1454,9 +1524,15 @@ private:
         }
     }
     
-    SIPConfigurationItemVisitorPtr updateGroup(const SIPGeneralGroupPtr&)
+    SIPConfigurationItemVisitorPtr updateGroup(const SIPGeneralGroupPtr& group)
     {
-        return 0;
+        if (!mGroup)
+        {
+            mGroup  = createGroupTemplate(group);
+        }
+       
+        return boost::shared_ptr<GeneralGroupConfig>(
+            new GeneralGroupConfig(mPJSIPManager, mGroup))->getVisitor();
     }
 
     SIPConfigurationItemVisitorPtr updateGroup(const SIPEndpointGroupPtr& group)
diff --git a/src/SIPEndpoint.cpp b/src/SIPEndpoint.cpp
index 1081e9c..e630e39 100644
--- a/src/SIPEndpoint.cpp
+++ b/src/SIPEndpoint.cpp
@@ -448,6 +448,21 @@ void SIPEndpoint::enableUDPTLTURN(bool enabled)
     mImplPriv->mConfig.sessionConfig.udptlWithTURN = enabled;
 }
 
+void SIPEndpoint::setMediaServiceName(const string& serviceName)
+{
+    mImplPriv->mConfig.sessionConfig.mediaServiceName = serviceName;
+}
+
+void SIPEndpoint::setUDPTLMediaServiceName(const string& serviceName)
+{
+    mImplPriv->mConfig.sessionConfig.udptlServiceName = serviceName;
+}
+
+void SIPEndpoint::setRoutingServiceName(const string& serviceName)
+{
+    mImplPriv->mConfig.sessionConfig.routingServiceName = serviceName;
+}
+
 void SIPEndpoint::setMediaNATOptions(bool useICE, bool useTURN)
 {
     mImplPriv->mConfig.sessionConfig.rtpOverICE = useICE;
diff --git a/src/SIPEndpoint.h b/src/SIPEndpoint.h
index cbf447f..c5fb88d 100644
--- a/src/SIPEndpoint.h
+++ b/src/SIPEndpoint.h
@@ -181,6 +181,24 @@ public:
     //
     bool rtpICEIncludeTURN;
 
+    //
+    // The service name identifier to use in locator queries for the RTP
+    // media component.
+    //
+    std::string mediaServiceName;
+
+    //
+    // The service name identifier to use in locator queries for the UDPTL
+    // component.
+    //
+    std::string udptlServiceName;
+
+    //
+    // The service name identifier to use in locator queries for the
+    // routing component.
+    //
+    std::string routingServiceName;
+
     SIPEndpointSessionConfig() :
         rtpOverIPv6(false),
         rtpOverICE(false),
@@ -355,6 +373,9 @@ public:
     void setUDPTLOverIPv6(bool);
     void enableUDPTLICE(bool);
     void enableUDPTLTURN(bool);
+    void setMediaServiceName(const std::string& serviceName);
+    void setUDPTLMediaServiceName(const std::string& serviceName);
+    void setRoutingServiceName(const std::string& serviceName);
     void addFormat(const std::string& name, int sampleRate, int frameSize, const Ice::StringSeq& formatSpecific);
 
     /**
diff --git a/src/SIPSession.cpp b/src/SIPSession.cpp
index a4d0849..a8d7169 100755
--- a/src/SIPSession.cpp
+++ b/src/SIPSession.cpp
@@ -2045,6 +2045,13 @@ public:
     {
         //lg(Debug) << "Sending new SIP INVITE to " << remote;
 
+        //
+        // XXX Why create a new instance of Session? A default copy is
+        // going to be a shallow copy which just copies the pointer to the
+        // internal state, ie. that data is still going to be shared. I'm
+        // not sure why thiis is necessary. Actually.. it doesn't seem to
+        // be used at all!
+        //
         // Record our session within the dialog so code handling pjsip events can do STUFF
         SIPSessionPtr session = new SIPSession(*mSession);
 
@@ -3081,10 +3088,15 @@ pjmedia_sdp_session *SIPSession::createSDPOffer(const AsteriskSCF::Media::V1::St
         // If this stream contains an audio or video format the stream is transported using RTP
         if ((audio = AudioFormatPtr::dynamicCast(formats.front())) || (video = VideoFormatPtr::dynamicCast(formats.front())))
         {
+            SIPEndpointConfig& config = mImplPriv->mEndpoint->getConfig();
             RTPServiceLocatorParamsPtr params = new RTPServiceLocatorParams();
             params->category = "rtp";
             params->formats = stream->second->formats;
             params->ipv6 = mImplPriv->mEndpoint->getConfig().sessionConfig.rtpOverIPv6;
+            if (!config.sessionConfig.mediaServiceName.empty())
+            {
+                params->service = config.sessionConfig.mediaServiceName;
+            }
 
             // Try to find a factory for RTP sessions matching what we need
             RTPMediaServicePrx factory = RTPMediaServicePrx::uncheckedCast(mImplPriv->mServiceLocator->locate(params));
@@ -3099,7 +3111,6 @@ pjmedia_sdp_session *SIPSession::createSDPOffer(const AsteriskSCF::Media::V1::St
             RTPOptionsPtr options(new RTPOptions());
             RTPAllocationOutputsPtr outputs;
 
-            SIPEndpointConfig& config = mImplPriv->mEndpoint->getConfig();
             if (config.sessionConfig.dtmf == AsteriskSCF::Configuration::SIPSessionManager::V1::RFC4733)
             {
                 options->handleTelephonyEvents = true;
@@ -3201,10 +3212,15 @@ pjmedia_sdp_session *SIPSession::createSDPOffer(const AsteriskSCF::Media::V1::St
             {
                 params = new AsteriskSCF::Media::UDPTL::V1::UDPTLServiceLocatorParams;
             }
+            SIPEndpointConfig config = mImplPriv->mEndpoint->getConfig();
 
             params->category = "udptl";
-            params->ipv6 = mImplPriv->mEndpoint->getConfig().sessionConfig.udptlOverIPv6;
-
+            params->ipv6 = config.sessionConfig.udptlOverIPv6;
+            if (!config.sessionConfig.udptlServiceName.empty())
+            {
+                params->service = config.sessionConfig.udptlServiceName;
+            }
+            
             UDPTLMediaServicePrx factory = UDPTLMediaServicePrx::uncheckedCast(mImplPriv->mServiceLocator->locate(params));
             if (factory == 0)
             {
@@ -3589,11 +3605,15 @@ pjmedia_sdp_session *SIPSession::createSDPAnswer(const pjmedia_sdp_session* offe
                 RTPOptionsPtr options(new RTPOptions());
                 RTPAllocationOutputsPtr outputs;
 
-                SIPEndpointConfig& config = mImplPriv->mEndpoint->getConfig();
+                SIPEndpointConfig config = mImplPriv->mEndpoint->getConfig();
                 if (config.sessionConfig.dtmf == AsteriskSCF::Configuration::SIPSessionManager::V1::RFC4733)
                 {
                     options->handleTelephonyEvents = true;
                 }
+                if (!config.sessionConfig.mediaServiceName.empty())
+                {
+                    params->service = config.sessionConfig.mediaServiceName;
+                }
 
                 session = factory->allocate(params, options, outputs);
 

commit 931b37bca7117716f7f6742d70ddeab0d3122f2b
Author: Brent Eagles <beagles at digium.com>
Date:   Wed Feb 8 11:33:31 2012 -0330

    Merging dev/jira-astscf-397-cryptokey-configuration.

diff --git a/config/Sip.config b/config/Sip.config
index b14323a..067a65f 100644
--- a/config/Sip.config
+++ b/config/Sip.config
@@ -171,6 +171,44 @@ ids=bob-bar-office,bob-bar-cell
 # dtmfmethod=rfc4733
 
 #
+# Enable SRTP authentication support (default: false)
+#
+# enableauth=false
+
+#
+# Enable SRTP encryption (default: false). Cipher suites and keys
+# should be defined if this is enabled.
+#
+# enableencryption=false
+
+#
+# Configuration cipher suites and their keys. More than one may be
+# defined and they must be defined in pairs and they must have a
+# suffix that identifies the pair. If a cryptosuite does not require a
+# key, simply enter a blank cryptokey property. If only one pair is
+# defined, a suffix may be omitted. These values are only processed if
+# encryption is enabled.
+#
+# Note: valid values are largely dependent on how pjsip is configured.
+#
+# WARNING: If multiple pairs are provided and suffixes are not used
+# properly, configuration mismatches will occur.
+#
+# ciphersuite=[cipher suite name]
+# cryptokey=[key or blank]
+#
+# AND OR
+#
+# ciphersuite[a suffix]=[cipher suite name]
+# cryptokey[a suffix]=[key or blank]
+#
+# eg.
+#
+# ciphersuite_a128=Awesome Suite 128bit
+# cryptokey_a128=Wx0wWhxAtxAxCRxAPPYKxEY
+#
+
+#
 # Example of configuring a STUN server for NAT handling.
 #
 # [transport_stun]
diff --git a/config/SipConfigurator.py b/config/SipConfigurator.py
index 49cc83f..4ba6cd7 100755
--- a/config/SipConfigurator.py
+++ b/config/SipConfigurator.py
@@ -24,7 +24,7 @@ import os, sys
 sys.path.append(os.environ["ASTSCF_HOME"] + "/configurator")
 sys.path.append("/opt/Ice-3.4/python")
 
-import ConfigParser, Ice, Configurator, traceback
+import ConfigParser, Ice, Configurator, traceback, uuid
 
 # Load our component specific configuration definitions
 Ice.loadSlice("--underscore -I\"" + os.environ["ASTSCF_HOME"] + "/slice/slice\"" + " -I" + Ice.getSliceDir() + " --all " + os.environ["ASTSCF_HOME"] + "/sip/slice/AsteriskSCF/Configuration/SIPSessionManager/SIPConfigurationIf.ice")
@@ -207,24 +207,75 @@ class SIPSectionVisitors(Configurator.SectionVisitors):
         mapper.map('enableturn', item, 'enableTURN', 'enableRTPICE', config.get, None)
 
         item = AsteriskSCF.Configuration.SIPSessionManager.V1.SRTPCryptoItem()
-               
+
+        #
+        # Maps key/suite pairs to SRTPCryptoKey configuration
+        # objects. It is a little suboptimal in how it goes about
+        # mapping multiple entries because it requires that the suite
+        # and keys that "belong together" appear right next to each
+        # other in the file. Kind of iffy, but parsing strings on
+        # delimiters might cause problems in that it is not clear what
+        # makes a safe delimiter.
+        #
         class CryptoKeyHandler:
-                def __init__(self, config, keyItem):
+                def __init__(self, config, item):
                     self.config = config
-                    self.item = keyItem
+                    self.cryptoItem = item
+
+                def enableEncryption(self, section, item):
+                    itemData = self.config.get(section, item)
+                    if not itemData or len(itemData) == 0 or itemData.lower() not in ["1", "true", "yes"]:
+                        self.cryptoItem.enableEncryption = False
+                        return
+
+                    #
+                    # Okay, so encryption is enabled. We scan the
+                    # items in the section looking for ciphersuite and
+                    # cryptokey pairs associated to each other with a
+                    # common suffix (suffix can be any string really).
+                    # If a suffix is not present, we provide a default
+                    # one based on UUID generation. There *is* a
+                    # potential for collision, but hey.
+                    #
+
+                    self.cryptoItem.enableEncryption = True
+                    
+                    cryptoKeyPairs = { }
 
-                def getSuite(self, section, item):
-                    self.item.suite = self.config.get(section, item)
+                    defaultSuffix = str(uuid.uuid1())
+                    
+                    #
+                    # Get the items for this section.
+                    #
+                    for key, value in self.config.items(section):
+                        if key.lower().startswith("ciphersuite"):
+                            suffix = key[len("ciphersuite"):len(key)]
+                            if len(suffix) == 0:
+                                suffix = defaultSuffix
+                            if suffix not in cryptoKeyPairs:
+                                cryptoKeyPairs[suffix] = [ value, "" ]
+                            else:
+                                cryptoKeyPairs[suffix][0] = value
+                        elif key.lower().startswith("cryptokey"):
+                            suffix = key[len("cryptokey"):len(key)]
+                            if len(suffix) == 0:
+                                suffix = defaultSuffix
+                            if suffix not in cryptoKeyPairs:
+                                cryptoKeyPairs[suffix] = [ "", value ]
+                            else:
+                                cryptoKeyPairs[suffix][1] = value
+
+                    for k in cryptoKeyPairs.values():
+                        cryptoKey = AsteriskSCF.Configuration.SIPSessionManager.V1.SRTPCryptoKey()
+                        cryptoKey.suite = k[0]
+                        cryptoKey.cryptoKey = k[1]
+                        self.cryptoItem.cryptoKeys.append(cryptoKey)
 
-                def getKey(self, section, item):
-                    self.item.cryptoKey = self.config.get(section, item)
                     
-        item.cryptoKeys = [ AsteriskSCF.Configuration.SIPSessionManager.V1.SRTPCryptoKey() ]
         mapper.map('enableauth', item, 'enableAuthentication', 'srtpCryptoSettings', config.get, None)
-        mapper.map('enableencryption', item, 'enableEncryption', 'srtpCryptoSettings', config.get, None)
-        handler = CryptoKeyHandler(config, item.cryptoKeys[0])
-        mapper.map('ciphersuite', item, 'suite', 'srtpCryptoSettings', handler.getSuite, None)
-        mapper.map('cryptokey', item, 'cryptoKey', 'srtpCryptoSettings', handler.getKey, None)
+        item.cryptoKeys = []
+        handler = CryptoKeyHandler(config, item)
+        mapper.map('enableencryption', item, 'enableEncryption', 'srtpCryptoSettings', handler.enableEncryption, None)
 
         class AllowableCallDirectionTransformer():
             def __init__(self, config):
diff --git a/src/Component.cpp b/src/Component.cpp
index 311b4eb..3da1d4e 100644
--- a/src/Component.cpp
+++ b/src/Component.cpp
@@ -228,6 +228,11 @@ void Component::preparePrimaryServicesForDiscovery()
  */
 void Component::prepareBackplaneServicesForDiscovery()
 {
+    //
+    // TODO: It would be much nicer if the base component did the default
+    // component intialization in a different method than that would be
+    // normally overridden by a derived class to add features.
+    //
     // Insure the default Component services are prepped.
     AsteriskSCF::Component::Component::prepareBackplaneServicesForDiscovery();
 
@@ -384,6 +389,9 @@ void Component::registerPJSIPModules()
         //module names to modules to the PJSIP session manager instead.
         //Since there's only a single configurable module at the moment,
         //we'll just do it here instead.
+        //
+        // TODO: update comment!
+        //
         if ((*i) == "Session")
         {
             mPJSIPManager->registerSessionModule(mEndpointFactory,
@@ -416,9 +424,9 @@ void Component::onPreInitialize()
 {
     try
     {
-        //As nice as it is of IceBox to provide us with a communicator,
-        //we're going to create our own so that we can provide it with a threadhook.
-        //Yes, this could be done via a plugin, but this is easier. Go away.
+        // As nice as it is of IceBox to provide us with a communicator,
+        // we're going to create our own so that we can provide it with a threadhook.
+        // Yes, this could be done via a plugin, but this is easier. Go away.
         Ice::InitializationData id;
         id.threadHook = new AsteriskSCF::PJLIB::ThreadHook("Ice");
         id.properties = getCommunicator()->getProperties();
diff --git a/src/SIPSession.cpp b/src/SIPSession.cpp
index 00ad31d..a4d0849 100755
--- a/src/SIPSession.cpp
+++ b/src/SIPSession.cpp
@@ -2825,11 +2825,6 @@ void SIPSession::addKeys(const SIPEndpointMediaSRTPConfig& config, pjmedia_sdp_m
 {
     if(!config.cryptoKeys.empty())
     {
-        //
-        // NOTE: AFAICT, we should really be able to supply multiple potential cyphersuites and keys.
-        // However, the configuration tool doesn't currently support that so what we'll do for now
-        // is provide support in the code and deal with the configuration issue later.
-        //
         int index = 1;
         for (CryptoKeys::const_iterator i = config.cryptoKeys.begin();
              i != config.cryptoKeys.end(); ++i)

commit 9bf9bf8fa1d3b95496a6c7571db5b9deda19bad7
Author: Ken Hunt <ken.hunt at digium.com>
Date:   Mon Feb 6 11:41:10 2012 -0600

    Correction for file name case change.

diff --git a/src/ComponentStateReplicator.cpp b/src/ComponentStateReplicator.cpp
index 9e0c561..34446c6 100644
--- a/src/ComponentStateReplicator.cpp
+++ b/src/ComponentStateReplicator.cpp
@@ -20,7 +20,7 @@
 
 #include <AsteriskSCF/Component/ComponentStateReplicator.h>
 #include <AsteriskSCF/Core/Discovery/ServiceLocatorIf.h>
-#include <AsteriskSCF/logger.h>
+#include <AsteriskSCF/Logger.h>
 
 #include <SIPIf.h>
 

commit 17b8c4b31831b58c48bab18d96d07023f29ca33d
Author: Ken Hunt <ken.hunt at digium.com>
Date:   Mon Feb 6 11:15:40 2012 -0600

    State replicator uses base ComponentStateReplicator class.

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index af74c6d..aa40d6f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -93,7 +93,7 @@ pjproject_link(SIPSessionManager pjlib)
 astscf_component_install(SIPSessionManager)
 
 astscf_component_init(SIPStateReplicator)
-astscf_component_add_files(SIPStateReplicator SIPStateReplicatorApp.cpp)
+astscf_component_add_files(SIPStateReplicator ComponentStateReplicator.cpp)
 astscf_component_add_files(SIPStateReplicator SIPStateReplicator.h)
 astscf_component_add_slices(SIPStateReplicator PROJECT SIPIf.ice)
 astscf_component_add_slices(SIPStateReplicator PROJECT AsteriskSCF/Replication/SIPSessionManager/SIPStateReplicationIf.ice)
@@ -104,3 +104,4 @@ astscf_component_add_slice_collection_libraries(SIPStateReplicator ASTSCF)
 astscf_component_build_icebox(SIPStateReplicator)
 target_link_libraries(SIPStateReplicator LoggingClient ASTSCFIceUtilCpp)
 astscf_component_install(SIPStateReplicator)
+
diff --git a/src/Component.cpp b/src/Component.cpp
index 904fd84..311b4eb 100644
--- a/src/Component.cpp
+++ b/src/Component.cpp
@@ -535,11 +535,11 @@ void Component::createPrimaryServices()
                     sipReplicationContext));
         lg(Debug) << "Created SIP endpoint factory";
 
-	    // Locate the Routing Service so that we can do routing. This is done here so it can be
+        // Locate the Routing Service so that we can do routing. This is done here so it can be
         // passed to the configuration service.
         // (NOTE: I suspect that since we're using a smart pointer,
         // this could be deferred to findRemoteServices)
-	    locateRoutingService();
+        locateRoutingService();
 
         // Create and configure our Endpoint Locator.
         mEndpointLocator = new SIPSessionManagerEndpointLocator(mEndpointFactory);
diff --git a/src/ComponentStateReplicator.cpp b/src/ComponentStateReplicator.cpp
new file mode 100644
index 0000000..9e0c561
--- /dev/null
+++ b/src/ComponentStateReplicator.cpp
@@ -0,0 +1,107 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+
+#include "SIPStateReplicator.h"
+
+#include <Ice/Ice.h>
+
+#include <AsteriskSCF/Component/ComponentStateReplicator.h>
+#include <AsteriskSCF/Core/Discovery/ServiceLocatorIf.h>
+#include <AsteriskSCF/logger.h>
+
+#include <SIPIf.h>
+
+using namespace std;
+using namespace AsteriskSCF::Core;
+using namespace AsteriskSCF::Core::Discovery::V1;
+using namespace AsteriskSCF::Replication::SIPSessionManager::V1;
+using namespace AsteriskSCF::System::Component::V1;
+using namespace AsteriskSCF::System::Logging;
+using namespace AsteriskSCF::SIPSessionManager;
+
+using namespace AsteriskSCF::Discovery;
+
+namespace
+{
+Logger lg = getLoggerFactory().getLogger("AsteriskSCF.SIPSessionManagerReplicator");
+}
+
+class ComponentStateReplicator : public AsteriskSCF::Component::ComponentStateReplicator
+{
+public:
+    ComponentStateReplicator() :
+      AsteriskSCF::Component::ComponentStateReplicator(lg, 
+          AsteriskSCF::Replication::SIPSessionManager::V1::StateReplicatorComponentCategory, 
+          true) // if true, supports configuration
+    {
+    }
+
+    ~ComponentStateReplicator() {}
+
+    ///////////////////////////////////////////////////
+    // Required overrides
+
+    void createPrimaryServices();
+    void preparePrimaryServicesForDiscovery();
+
+
+private:
+    SIPStateReplicatorIPtr mStateReplicator;
+    SIPStateReplicatorPrx mStateReplicatorPrx;
+    LocatorRegistrationWrapperPtr mStateReplicatorRegistration;
+};
+
+static const string ComponentServiceId("SIPStateReplicatorComponent");
+static const string ServiceDiscoveryId("SIPStateReplicatorService");
+
+/**
+ * Register this component's primary public interfaces with the Service Locator.
+ * This enables other Asterisk SCF components to locate our interfaces.
+ */
+void ComponentStateReplicator::preparePrimaryServicesForDiscovery()
+{
+    try
+    {
+        // Wrap our authentication extensions point for the Service Locator.
+        mStateReplicatorRegistration = wrapServiceForRegistration(mStateReplicatorPrx,
+                                                                  AsteriskSCF::Replication::SIPSessionManager::V1::StateReplicatorDiscoveryCategory);
+        managePrimaryService(mStateReplicatorRegistration);
+    }
+    catch(const std::exception& e)
+    {
+        lg(Error) << "Unable to publish component interfaces in " << getName() << BOOST_CURRENT_FUNCTION <<
+            ". Exception: " << e.what();
+        throw; // rethrow
+    }
+}
+
+void ComponentStateReplicator::createPrimaryServices()
+{
+    // Create the sip state replicator servant
+    mStateReplicator = new SIPStateReplicatorI();
+
+    mStateReplicatorPrx = SIPStateReplicatorPrx::uncheckedCast(
+       getServiceAdapter()->add(mStateReplicator, getCommunicator()->stringToIdentity(ServiceDiscoveryId)));
+}
+
+extern "C"
+{
+ASTSCF_DLL_EXPORT IceBox::Service* create(Ice::CommunicatorPtr)
+{
+    return new ComponentStateReplicator;
+}
+}
+
diff --git a/src/SIPStateReplicatorApp.cpp b/src/SIPStateReplicatorApp.cpp
deleted file mode 100644
index 7cef615..0000000
--- a/src/SIPStateReplicatorApp.cpp
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Asterisk SCF -- An open-source communications framework.
- *
- * Copyright (C) 2010, Digium, Inc.
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk SCF project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE.txt file
- * at the top of the source tree.
- */
-
-#include "SIPStateReplicator.h"
-
-#include <Ice/Ice.h>
-#include <IceUtil/UUID.h>
-#include <IceStorm/IceStorm.h>
-#include <IceBox/IceBox.h>
-
-#include <AsteriskSCF/Core/Discovery/ServiceLocatorIf.h>
-#include <AsteriskSCF/System/Component/ComponentServiceIf.h>
-#include <AsteriskSCF/Logger.h>
-#include <AsteriskSCF/Logger/IceLogger.h>
-#include <AsteriskSCF/CollocatedIceStorm/CollocatedIceStorm.h>
-#include <AsteriskSCF/System/Component/ConfigurationIf.h>
-
-#include <SIPIf.h>
-
-#include "SIPConfigurationIf.h"
-
-using namespace std;
-using namespace AsteriskSCF::Core;
-using namespace AsteriskSCF::Core::Discovery::V1;
-using namespace AsteriskSCF::Replication::SIPSessionManager::V1;
-using namespace AsteriskSCF::Configuration::SIPSessionManager::V1;
-using namespace AsteriskSCF::System::Component::V1;
-using namespace AsteriskSCF::System::Logging;
-using namespace AsteriskSCF::SIPSessionManager;
-using namespace AsteriskSCF::CollocatedIceStorm;
-using namespace AsteriskSCF::System::Configuration::V1;
-
-namespace
-{
-Logger lg = getLoggerFactory().getLogger("AsteriskSCF.SIPSessionGatewayReplicator");
-}
-
-class SIPStateReplicatorService : public IceBox::Service
-{
-public:
-    SIPStateReplicatorService() { };
-    ~SIPStateReplicatorService()
-    {
-        mComponentService = 0;
-        mAdapter = 0;
-        mStateReplicator = 0;
-	mConfigurationReplicator = 0;
-    };
-    virtual void start(const string &name, const Ice::CommunicatorPtr& ic, const Ice::StringSeq& args);
-    virtual void stop();
-private:
-    void initialize(const std::string& appName, const Ice::CommunicatorPtr& ic);
-    void registerWithServiceLocator(const Ice::CommunicatorPtr& ic);
-    void deregisterFromServiceLocator();
-    std::string mAppName;
-    //vector<SIPStateReplicatorListenerPrx> mListeners;
-    Ice::ObjectAdapterPtr mAdapter;
-    ServiceLocatorManagementPrx mServiceLocatorManagement;
-    Discovery::V1::ServiceManagementPrx mComponentServiceManagement;
-    Discovery::V1::ServiceManagementPrx mStateReplicationManagement;
-    ConfiguredIceLoggerPtr mIceLogger;
-    ComponentServicePtr mComponentService;
-    SIPStateReplicatorIPtr mStateReplicator;
-    ConfigurationReplicatorPtr mConfigurationReplicator;
-    CollocatedIceStormPtr mIceStorm;
-    Ice::ObjectPrx mConfigurationPublisher;
-    Discovery::V1::ServiceManagementPrx mConfigurationManagement;
-    std::string mConfigCompareGuid;
-};
-
-static const string ComponentServiceId("SIPStateReplicatorComponent");
-static const string ServiceDiscoveryId("SIPStateReplicatorService");
-
-/**
- * This class provides implementation for the ComponentService interface, which
- * every Asterisk SCF component is expected to publish.
- */
-class ComponentServiceImpl : public ComponentService
-{
-public:
-    ComponentServiceImpl(SIPStateReplicatorService &service) : mService(service) {}
-
-public: // Overrides of the ComponentService interface.
-    virtual void suspend(const ::Ice::Current& = ::Ice::Current())
-    {
-        // TBD
-    }
-
-    virtual void resume(const ::Ice::Current& = ::Ice::Current())
-    {
-        // TBD
-    }
-
-    virtual void shutdown(const ::Ice::Current& = ::Ice::Current())
-    {
-        // TBD
-    }
-
-private:
-    SIPStateReplicatorService& mService; // TODO: Reference?
-};
-
-class ConfigurationReplicatorI : public ConfigurationReplicator
-{
-public:
-    ConfigurationReplicatorI(const IceStorm::TopicPrx& topic) : mConfigurationReplicationTopic(topic) { };
-    void registerConfigurationService(const AsteriskSCF::System::Configuration::V1::ConfigurationServicePrx&, const Ice::Current&);
-private:
-    IceStorm::TopicPrx mConfigurationReplicationTopic;
-};
-
-void ConfigurationReplicatorI::registerConfigurationService(const AsteriskSCF::System::Configuration::V1::ConfigurationServicePrx& service, const Ice::Current&)
-{
-    if (mConfigurationReplicationTopic)
-    {
-	IceStorm::QoS qos;
-        qos["reliability"] = "ordered";
-
-        try
-        {
-            mConfigurationReplicationTopic->subscribeAndGetPublisher(qos, service);
-        }
-        catch (const IceStorm::AlreadySubscribed&)
-        {
-            // This is perfectly okay actually, it just means what they wanted us to do
-            // is already done.
-        }
-    }
-}
-
-/**
- * Register this component's primary public interfaces with the Service Locator.
- * This enables other Asterisk SCF components to locate our interfaces.
- */
-void SIPStateReplicatorService::registerWithServiceLocator(const Ice::CommunicatorPtr& ic)
-{
-    try
-    {
-        // Get a proxy to the management interface for the Service Locator, so we can add ourselves into the system
-        // discovery mechanisms.
-        mServiceLocatorManagement = ServiceLocatorManagementPrx::checkedCast(
-            ic->propertyToProxy("LocatorServiceManagement.Proxy"));
-
-        if (mServiceLocatorManagement == 0)
-        {
-            lg(Error) << "Unable to obtain proxy to ServiceLocatorManagement interface. Check config file. "
-                "This component can't be found until this is corrected.";
-            return;
-        }
-
-        // Get a proxy to our ComponentService interface and add it to the Service Locator.
-        Ice::ObjectPrx componentServiceObjectPrx =
-            mAdapter->createDirectProxy(ic->stringToIdentity(ComponentServiceId));
-        ComponentServicePrx componentServicePrx = ComponentServicePrx::checkedCast(componentServiceObjectPrx);
-
-        // The GUID passed in to add service needs to be unique for reporting.
-        string componentServiceGuid(StateReplicatorComponentCategory);
-        mComponentServiceManagement = ServiceManagementPrx::uncheckedCast(
-            mServiceLocatorManagement->addService(componentServicePrx, componentServiceGuid));
-
-        // Add category as a parameter to enable other components look this component up.
-        ServiceLocatorParamsPtr genericparams = new ServiceLocatorParams();
-        genericparams->category = StateReplicatorComponentCategory;
-
-        mComponentServiceManagement->addLocatorParams(genericparams, "");
-
-        Ice::ObjectPrx stateReplicatorObjectPrx = mAdapter->createDirectProxy(ic->stringToIdentity(ServiceDiscoveryId));
-        SIPStateReplicatorPrx stateReplicatorPrx = SIPStateReplicatorPrx::checkedCast(stateReplicatorObjectPrx);
-
-        string stateReplicationGuid(StateReplicatorDiscoveryCategory);
-        mStateReplicationManagement = ServiceManagementPrx::uncheckedCast(
-            mServiceLocatorManagement->addService(stateReplicatorPrx, stateReplicationGuid));
-
-        ServiceLocatorParamsPtr discoveryParams = new ServiceLocatorParams();
-        discoveryParams->category = StateReplicatorDiscoveryCategory;
-        discoveryParams->service = ic->getProperties()->getPropertyWithDefault(mAppName + ".ServiceName", 
-            "default");
-        discoveryParams->id = ic->getProperties()->getPropertyWithDefault(mAppName + ".Name", "default");
-        mStateReplicationManagement->addLocatorParams(discoveryParams, "");
-
-        // Publish the configuration service IceStorm topic so everybody gets configuration
-        mConfigurationManagement = ServiceManagementPrx::uncheckedCast(
-            mServiceLocatorManagement->addService(mConfigurationPublisher, ""));
-
-        // Populate the configuration parameters with details so we can be found
-        ServiceLocatorParamsPtr configurationParams = new ServiceLocatorParams();
-        configurationParams->category = ConfigurationDiscoveryCategory;
-        configurationParams->service = ic->getProperties()->getPropertyWithDefault(mAppName + ".ServiceName", 
-            "default");
-        configurationParams->id = ic->getProperties()->getPropertyWithDefault(mAppName + ".Name", "");
-        mConfigurationManagement->addLocatorParams(configurationParams, "");
-
-        // TBD... We may have other interfaces to publish to the Service Locator.
-    }
-    catch(...)
-    {
-        lg(Error) << "Exception in " << mAppName << " registerWithServiceLocator()" << endl;
-    }
-}
-
-/**
- * Deregister this component's primary public interfaces from the Service Locator.
- * This is done at shutdown, and whenever we want to keep other services from locating
- * our interfaces.
- */
-void SIPStateReplicatorService::deregisterFromServiceLocator()
-{
-    try
-    {
-        mComponentServiceManagement->unregister();
-	mConfigurationManagement->unregister();
-	mServiceLocatorManagement->removeCompare(mConfigCompareGuid);
-    }
-    catch(...)
-    {
-        lg(Error) << "Had trouble in deregisterFromServiceLocator()." << endl;
-    }
-}
-
-void SIPStateReplicatorService::initialize(const std::string& appName, const Ice::CommunicatorPtr& ic)
-{
-    mIceStorm = new CollocatedIceStorm(appName, ic->getProperties());
-    IceStorm::TopicManagerPrx topicManager = mIceStorm->createTopicManagerProxy(ic);
-
-    IceStorm::TopicPrx topic;
-
-    if (topicManager)
-    {
-        try
-        {
-            topic = topicManager->retrieve("ConfigurationReplication");
-        }
-        catch (const IceStorm::NoSuchTopic&)
-        {
-            try
-            {
-                topic = topicManager->create("ConfigurationReplication");
-            }
-            catch (const IceStorm::TopicExists&)
-            {
-                lg(Error) << "Oh snap! Race condition creating topic, aborting";
-                return;
-            }
-        }
-        // There is no cast here on purpose as this is just going to get passed to
-        // the service locator which just takes a plain ol' proxy anyway.
-        mConfigurationPublisher = topic->getPublisher();
-    }
-    else
-    {
-        lg(Info) << "IceStorm topic manager proxy not present, unable to perform configuration replication.";
-    }
-
-    mAdapter = ic->createObjectAdapter(appName + ".Adapter");
-
-    // setup logging client
-    mIceLogger = createIceLogger(mAdapter);
-    getLoggerFactory().setLogOutput(mIceLogger->getLogger());
-
-    mAppName = appName;
-    // Create and publish our ComponentService interface support.
-    mComponentService = new ComponentServiceImpl(*this);
-    mAdapter->add(mComponentService, ic->stringToIdentity(ComponentServiceId));
-    mStateReplicator = new SIPStateReplicatorI();
-    mAdapter->add(mStateReplicator, ic->stringToIdentity(ServiceDiscoveryId));
-    mConfigurationReplicator = new ConfigurationReplicatorI(topic);
-    mAdapter->addFacet(mConfigurationReplicator, ic->stringToIdentity(ServiceDiscoveryId),
-	ReplicatorFacet);
-
-    mAdapter->activate();
-}
-
-void SIPStateReplicatorService::start(const string& name, const Ice::CommunicatorPtr& ic, const Ice::StringSeq&)
-{
-    initialize(name, ic);
-    // Plug into the Asterisk SCF discovery system so that the interfaces we provide
-    // can be located.
-    registerWithServiceLocator(ic);
-}
-
-void SIPStateReplicatorService::stop()
-{
-    // Remove our interfaces from the service locator.
-    deregisterFromServiceLocator();
-
-    // Stop our local IceStorm instance
-    mIceStorm->stop();
-}
-
-extern "C"
-{
-ASTSCF_DLL_EXPORT IceBox::Service* create(Ice::CommunicatorPtr)
-{
-    return new SIPStateReplicatorService;
-}
-}
-

commit dd69b74a39e35efd82b59087c3f69224ccee531e
Author: Brent Eagles <beagles at digium.com>
Date:   Tue Jan 17 14:29:49 2012 -0330

    Fix the STUN module's destroyImpl() implementation so it only attempts to
    release the resources once. The previous impl would likely crash if
    destroy() was called because the cleanup was attempted once again in the
    destructor.

diff --git a/src/STUNModule.cpp b/src/STUNModule.cpp
index 0af4cac..bdb917b 100644
--- a/src/STUNModule.cpp
+++ b/src/STUNModule.cpp
@@ -149,10 +149,18 @@ STUNModule::STUNModule(const boost::shared_ptr<pj_stun_config>& config) :
 void STUNModule::destroyImpl()
 {
     boost::unique_lock<boost::shared_mutex> lock(mLock);
-    pj_ioqueue_destroy(mConfig->ioqueue);
-    pj_timer_heap_destroy(mConfig->timer_heap);
-    pj_pool_release(mPool);
-    mConfig.reset();
+    //
+    // The check for null on mConfig is necessary because if destroy() is
+    // called (which it might), the destructor is going to run through this
+    // code again.
+    //
+    if (mConfig)
+    {
+        pj_ioqueue_destroy(mConfig->ioqueue);
+        pj_timer_heap_destroy(mConfig->timer_heap);
+        pj_pool_release(mPool);
+        mConfig.reset();
+    }
 }
 }
 }

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


-- 
asterisk-scf/integration/sip.git



More information about the asterisk-scf-commits mailing list