[asterisk-scf-commits] asterisk-scf/integration/file_session_gateway.git branch "initial_development" updated.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Thu Dec 1 10:01:20 CST 2011


branch "initial_development" has been updated
       via  14fe2bc3b206ca70ae95f2e2537df1bbd32068ae (commit)
       via  99b551bf212cb40f301d4f8b1cd6ae8684e813e1 (commit)
       via  08e0374f2d8df503f5e1765d62a52c0ce7c58102 (commit)
      from  8e0d0f4e904a813389480705f724858b7eac505b (commit)

Summary of changes:
 CMakeLists.txt                                     |    2 +-
 TODO.txt                                           |   23 ++
 config/FileSessionGatewayConfigurator.py           |  361 ++------------------
 .../FileSessionGatewayConfigurationIf.ice          |   56 ++--
 .../FileSessionReplicationIf.ice                   |   10 +-
 src/CMakeLists.txt                                 |   30 +-
 src/Component.cpp                                  |   17 +-
 src/Configuration.cpp                              |  363 +++++++++++++++-----
 src/Configuration.h                                |    3 +-
 src/Endpoint.cpp                                   |  281 ++++++++++++---
 src/Endpoint.h                                     |   75 +++--
 src/EndpointLocator.cpp                            |  177 ++++++----
 src/EndpointLocator.h                              |   18 +-
 src/EndpointSpecification.h                        |   57 +++-
 src/FileSessionGatewayReplicator.cpp               |  218 ++++++++++++
 src/ReplicationAdapter.h                           |   36 ++-
 src/ReplicationListener.cpp                        |   95 ++++--
 src/ReplicationListener.h                          |    2 +-
 src/Session.cpp                                    |   60 ++--
 test/CMakeLists.txt                                |   29 ++-
 test/TODO.txt                                      |   23 ++
 test/TestEndpointLocator.cpp                       |  233 +++++++++++++
 test/TestSessionObject.cpp                         |  181 ++++++++++-
 23 files changed, 1633 insertions(+), 717 deletions(-)
 create mode 100644 TODO.txt
 create mode 100644 src/FileSessionGatewayReplicator.cpp
 create mode 100644 test/TODO.txt
 create mode 100644 test/TestEndpointLocator.cpp


- Log -----------------------------------------------------------------
commit 14fe2bc3b206ca70ae95f2e2537df1bbd32068ae
Author: Brent Eagles <beagles at digium.com>
Date:   Thu Dec 1 12:30:29 2011 -0330

    Configuration fixups.

diff --git a/slice/AsteriskSCF/Configuration/FileSessionGateway/FileSessionGatewayConfigurationIf.ice b/slice/AsteriskSCF/Configuration/FileSessionGateway/FileSessionGatewayConfigurationIf.ice
index 94dcd17..47a8809 100644
--- a/slice/AsteriskSCF/Configuration/FileSessionGateway/FileSessionGatewayConfigurationIf.ice
+++ b/slice/AsteriskSCF/Configuration/FileSessionGateway/FileSessionGatewayConfigurationIf.ice
@@ -75,14 +75,35 @@ local class ConfigurationItemVisitor extends AsteriskSCF::System::Configuration:
 };
 
 /**
- * Endpoint group, used to configure an endpoint
+ * Routing service configuration item
  */
-class EndpointGroup extends ConfigurationGroup
+const string RoutingServiceItem = "routingService";
+class RoutingService extends ConfigurationItem
 {
     /**
-     *  A unique id
+     * Name of the routing service to use
      */
-    string id;
+    string serviceName;
+};
+
+/**
+ * RTP Media service configuration item
+ */
+const string FileMediaServiceItem = "fileMediaServiceName";
+class FileMediaService extends ConfigurationItem
+{
+    /**
+     * Name of the File media service to use
+     */
+    string serviceName;
+};
+
+/**
+ * Endpoint group, used to configure an endpoint
+ */
+class EndpointGroup extends ConfigurationGroup
+{
+    string name;
 };
 
 /**
@@ -90,6 +111,7 @@ class EndpointGroup extends ConfigurationGroup
  * Destination string for the endpoint. 
  * 
  */
+const string EndpointDestinationItem = "endpointDestination";
 class EndpointDestinationName extends ConfigurationItem
 {
     string value;
@@ -97,9 +119,10 @@ class EndpointDestinationName extends ConfigurationItem
 
 /**
  *
- * Media file specification for .
+ * Media file specification for the endpoint's media file.
  *
  **/
+const string EndpointMediaFileItem = "endpointMediaFile";
 class MediaFile extends ConfigurationItem
 {
     /**
@@ -113,29 +136,6 @@ class MediaFile extends ConfigurationItem
     AsteriskSCF::Media::File::V1::FileOperations operations =
         AsteriskSCF::Media::File::V1::Playback;
 };
-
-/**
- * Routing service configuration item
- */
-class RoutingItem extends ConfigurationItem
-{
-    /**
-     * Name of the routing service to use
-     */
-    string routingServiceName;
-};
-
-/**
- * RTP Media service configuration item
- */
-class FileMediaServiceItem extends ConfigurationItem
-{
-    /**
-     * Name of the File media service to use
-     */
-    string mediaServiceName;
-};
-
 }; /* module V1 */
 
 }; /* module FileSessionGateway */
diff --git a/src/Configuration.cpp b/src/Configuration.cpp
index 4670d1b..199fd97 100644
--- a/src/Configuration.cpp
+++ b/src/Configuration.cpp
@@ -34,145 +34,316 @@ using namespace std;
 
 namespace 
 {
-    class ConfigurationImpl : public AsteriskSCF::System::Configuration::V1::ConfigurationService
+
+EndpointGroupPtr createGroupForEndpoint(const EndpointImplPtr& endpoint)
+{
+    EndpointSpecificationPtr spec = endpoint->getSpecification();
+    EndpointGroupPtr endpointGroup = new EndpointGroup;
+    endpointGroup->name = spec->name;
+
+    EndpointDestinationNamePtr destination = new EndpointDestinationName;
+    destination->value = spec->destination;
+    endpointGroup->configurationItems[EndpointDestinationItem] = destination;
+    
+    MediaFilePtr mediaFile = new MediaFile;
+    mediaFile->id = spec->mediaFile;
+    mediaFile->operations = spec->operations;
+    endpointGroup->configurationItems[EndpointMediaFileItem] = mediaFile;
+    return endpointGroup;
+}
+
+EndpointSpecificationPtr createSpecificationFromGroup(const EndpointGroupPtr& group)
+{
+    if (!group || group->name.empty())
+    {
+        return EndpointSpecificationPtr();
+    }
+    EndpointSpecificationPtr newSpec(new EndpointSpecification);
+    newSpec->name = group->name;
+
+    ConfigurationItemDict::iterator propertyIter = group->configurationItems.find(EndpointDestinationItem);
+    if (propertyIter != group->configurationItems.end())
     {
-    public:
-        ConfigurationImpl(const EndpointLocatorImplPtr& endpointLocator,
-            const Logger& logger) :
-            mEndpointLocator(endpointLocator),
-            mLogger(logger)
+        EndpointDestinationNamePtr destination = EndpointDestinationNamePtr::dynamicCast(propertyIter->second);
+        if (destination)
         {
+            newSpec->destination = destination->value;
         }
+    }
 
-        ConfigurationGroupSeq getConfiguration(const ConfigurationGroupSeq& groups, const Ice::Current&)
+    propertyIter = group->configurationItems.find(EndpointMediaFileItem);
+    if (propertyIter != group->configurationItems.end())
+    {
+        MediaFilePtr mediaFile = MediaFilePtr::dynamicCast(propertyIter->second);
+        if (mediaFile)
         {
-            ConfigurationGroupSeq result;
-            for (ConfigurationGroupSeq::const_iterator iter = groups.begin(); iter != groups.end(); ++iter)
-            {
-                //
-                // There aren't a lot of different types, so the visitor is a little overkill.
-                //
-                EndpointGroupPtr endpointGroup = EndpointGroupPtr::dynamicCast(*iter);
-                if (endpointGroup)
-                {
-                }
-            }
-            return result;
+            newSpec->mediaFile = mediaFile->id;
+            newSpec->operations = mediaFile->operations;
         }
+    }
+    return newSpec;
+}
+
+class ConfigurationImpl : public AsteriskSCF::System::Configuration::V1::ConfigurationService
+{
+public:
+    ConfigurationImpl(const EndpointLocatorImplPtr& endpointLocator,
+        const Logger& logger) :
+        mEndpointLocator(endpointLocator),
+        mLogger(logger)
+    {
+    }
 
-        ConfigurationGroupSeq getConfigurationAll(const ConfigurationGroupSeq& groups, const Ice::Current&)
+    ConfigurationGroupSeq getConfiguration(const ConfigurationGroupSeq& groups, const Ice::Current&)
+    {
+        ConfigurationGroupSeq result;
+        for (ConfigurationGroupSeq::const_iterator iter = groups.begin(); iter != groups.end(); ++iter)
         {
-            ConfigurationGroupSeq result;
-            for (ConfigurationGroupSeq::const_iterator iter = groups.begin(); iter != groups.end(); ++iter)
+            //
+            // There aren't a lot of different types, so the visitor is a little overkill.
+            //
+            EndpointGroupPtr endpointGroup = EndpointGroupPtr::dynamicCast(*iter);
+            if (endpointGroup)
             {
-                //
-                // There aren't a lot of different types, so the visitor is a little overkill.
-                //
-                EndpointGroupPtr endpointGroup = EndpointGroupPtr::dynamicCast(*iter);
-                result.push_back(endpointGroup);
-                if (endpointGroup)
+                EndpointImplSeq endpointImpls = mEndpointLocator->getEndpoints();
+                for (EndpointImplSeq::const_iterator endpointIter = endpointImpls.begin();
+                     endpointIter != endpointImpls.end(); ++endpointIter)
                 {
-                    EndpointGroupPtr group = new EndpointGroup;
-                    group->id = mEndpointLocator->getId();
-                    EndpointImplSeq impls = mEndpointLocator->getEndpoints();
-                    for (EndpointImplSeq::const_iterator endpointIter = impls.begin(); endpointIter != impls.end();
-                         ++endpointIter)
+                    if (endpointGroup->name == (*endpointIter)->getName())
                     {
-                        EndpointSpecificationPtr spec = (*endpointIter)->getSpecification();
-                        
+                        result.push_back(createGroupForEndpoint(*endpointIter));
                     }
                 }
+                continue;
             }
-            return result;
-        }
 
-        ConfigurationGroupSeq getConfigurationGroups(const Ice::Current&)
-        {
-            ConfigurationGroupSeq groups;
-            EndpointGroupPtr group = new EndpointGroup;
-            group->id = mEndpointLocator->getId(); 
-            groups.push_back(group);
-            return groups;
-        }
+            //
+            // TODO: get from something real.
+            //
+            GeneralGroupPtr generalGroup = GeneralGroupPtr::dynamicCast(*iter);
+            if (generalGroup)
+            {
+                RoutingServicePtr routingService = new RoutingService;
+                routingService->serviceName = "default";
+                generalGroup->configurationItems[RoutingServiceItem] = routingService;
 
-        void setConfiguration(const ConfigurationGroupSeq&, const Ice::Current&)
-        {
+                FileMediaServicePtr fileMediaService = new FileMediaService;
+                fileMediaService->serviceName = "default";
+                generalGroup->configurationItems[FileMediaServiceItem] = fileMediaService;
+            }
         }
+        return result;
+    }
 
-        void removeConfigurationItems(const ConfigurationGroupSeq&, const Ice::Current&)
+    ConfigurationGroupSeq getConfigurationAll(const ConfigurationGroupSeq& groups, const Ice::Current&)
+    {
+        ConfigurationGroupSeq result;
+        for (ConfigurationGroupSeq::const_iterator iter = groups.begin(); iter != groups.end(); ++iter)
         {
+            //
+            // There aren't a lot of different types, so the visitor is a little overkill.
+            //
+            EndpointGroupPtr endpointGroup = EndpointGroupPtr::dynamicCast(*iter);
+            if (endpointGroup)
+            {
+                EndpointImplSeq endpointImpls = mEndpointLocator->getEndpoints();
+                for (EndpointImplSeq::const_iterator endpointIter = endpointImpls.begin();
+                     endpointIter != endpointImpls.end(); ++endpointIter)
+                {
+                    result.push_back(createGroupForEndpoint(*endpointIter));
+                }
+                continue;
+            }
+            //
+            // TODO: get from something real.
+            //
+            GeneralGroupPtr generalGroup = GeneralGroupPtr::dynamicCast(*iter);
+            if (generalGroup)
+            {
+                RoutingServicePtr routingService = new RoutingService;
+                routingService->serviceName = "default";
+                generalGroup->configurationItems[RoutingServiceItem] = routingService;
+
+                FileMediaServicePtr fileMediaService = new FileMediaService;
+                fileMediaService->serviceName = "default";
+                generalGroup->configurationItems[FileMediaServiceItem] = fileMediaService;
+            }
         }
 
-        void removeConfigurationGroups(const ConfigurationGroupSeq&, const Ice::Current&)
+        return result;
+    }
+
+    ConfigurationGroupSeq getConfigurationGroups(const Ice::Current&)
+    {
+        ConfigurationGroupSeq groups;
+        
+        EndpointImplSeq endpointImpls = mEndpointLocator->getEndpoints();
+        for (EndpointImplSeq::const_iterator iter = endpointImpls.begin();
+             iter != endpointImpls.end(); ++iter)
         {
+            EndpointGroupPtr endpointGroup = new EndpointGroup;
+            endpointGroup->name = (*iter)->getName();
+            groups.push_back(endpointGroup);
         }
-    private:
-        EndpointLocatorImplPtr mEndpointLocator;
-        Logger mLogger;
-    };
-    typedef IceUtil::Handle<ConfigurationImpl> ConfigurationImplPtr;
+        groups.push_back(new GeneralGroup);
+        return groups;
+    }
 
-    class ConfigurationFeature : public ComponentFeature
+    void setConfiguration(const ConfigurationGroupSeq& config, const Ice::Current&)
     {
-    public:
-        ConfigurationFeature(const EndpointLocatorImplPtr& endpointLocator, const Logger& logger) :
-            mServant(new ConfigurationImpl(endpointLocator, logger)),
-            mId(std::string("ascf.fsgtw.") + IceUtil::generateUUID()),
-            mLogger(logger)
+        EndpointSpecificationSeq newSpecs;
+        for (ConfigurationGroupSeq::const_iterator configIter = config.begin();
+             configIter != config.end(); ++configIter)
         {
-        }
+            EndpointGroupPtr endpointGroup = EndpointGroupPtr::dynamicCast(*configIter);
+            if (endpointGroup)
+            {
+                newSpecs.push_back(createSpecificationFromGroup(endpointGroup));
+                continue;
+            }
+            GeneralGroupPtr generalGroup = GeneralGroupPtr::dynamicCast(*configIter);
+            if (generalGroup)
+            {
+                ConfigurationItemDict::const_iterator itemIter = generalGroup->configurationItems.find(
+                    RoutingServiceItem);
+                if (itemIter != generalGroup->configurationItems.end())
+                {
+                    RoutingServicePtr routingService = RoutingServicePtr::dynamicCast(itemIter->second);
+                    if (routingService)
+                    {
+                        //
+                        // TODO: we do not have a central configuration for this yet.
+                        //
+                    }
+                    continue;
+                }
 
-        Ice::ObjectPrx activate(const Ice::ObjectAdapterPtr& adapter)
+                itemIter = generalGroup->configurationItems.find(FileMediaServiceItem);
+                if (itemIter != generalGroup->configurationItems.end())
+                {
+                    FileMediaServicePtr fileMediaService = FileMediaServicePtr::dynamicCast(itemIter->second);
+                    if (fileMediaService)
+                    {
+                        //
+                        // TODO: we do not have a central configuration for this yet.
+                        //
+                    }
+                    continue;
+                }
+
+            }
+        }
+        if (!newSpecs.empty())
         {
-            Ice::Identity id(adapter->getCommunicator()->stringToIdentity(mId));
-            mPublicProxy = ConfigurationServicePrx::uncheckedCast(adapter->add(mServant, id));
-            mDirectProxy = ConfigurationServicePrx::uncheckedCast(adapter->createDirectProxy(id));
-            return mDirectProxy;
+            mEndpointLocator->addEndpoints(newSpecs);
         }
+    }
 
-        void registerFeature(const FileSessionGatewayComponentPtr& gatewayComponent)
+    //
+    // TODO: The configuration is not really decomposeable in this way, so I will need to look at this more
+    // closely.
+    //
+    void removeConfigurationItems(const ConfigurationGroupSeq&, const Ice::Current&)
+    {
+    }
+
+    void removeConfigurationGroups(const ConfigurationGroupSeq& config, const Ice::Current&)
+    {
+        EndpointSpecificationSeq specsToRemove;
+        EndpointImplSeq endpoints = mEndpointLocator->getEndpoints();
+        for (ConfigurationGroupSeq::const_iterator configIter = config.begin();
+             configIter != config.end(); ++configIter)
         {
-            assert(gatewayComponent);
-            if (gatewayComponent)
+            EndpointGroupPtr endpointGroup = EndpointGroupPtr::dynamicCast(*configIter);
+            if (endpointGroup)
             {
-                //
-                // This should be a public proxy because if we fail over to a
-                // replica, we want the proxy in discovery to be remain generally
-                // valid.
-                //
-                gatewayComponent->addFeatureProxyToBackplane(mPublicProxy, 
-                    AsteriskSCF::Configuration::FileSessionGateway::V1::ConfigurationDiscoveryCategory);
-            }
-            else
-            {
-                mLogger(Error) << "Unable to register configuration service. Provided component reference is nil";
+                for (EndpointImplSeq::const_iterator endpointIter = endpoints.begin();
+                     endpointIter != endpoints.end(); ++endpointIter)
+                {
+                    EndpointSpecificationPtr spec = (*endpointIter)->getSpecification();
+                    if (spec->name == endpointGroup->name)
+                    {
+                        specsToRemove.push_back(spec);
+                        break;
+                    }
+                }
             }
         }
 
-        void makeReady(const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& /* locator */,
-            const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr& /* params */)
+        if (!specsToRemove.empty())
         {
-            // XXX
+            mEndpointLocator->removeEndpoints(specsToRemove);
         }
+    }
+private:
+    EndpointLocatorImplPtr mEndpointLocator;
+    Logger mLogger;
+};
+typedef IceUtil::Handle<ConfigurationImpl> ConfigurationImplPtr;
+
+class ConfigurationFeature : public ComponentFeature
+{
+public:
+    ConfigurationFeature(const EndpointLocatorImplPtr& endpointLocator, const Logger& logger) :
+        mServant(new ConfigurationImpl(endpointLocator, logger)),
+        mId(std::string("ascf.fsgtw.") + IceUtil::generateUUID()),
+        mLogger(logger)
+    {
+    }
+
+    Ice::ObjectPrx activate(const Ice::ObjectAdapterPtr& adapter)
+    {
+        Ice::Identity id(adapter->getCommunicator()->stringToIdentity(mId));
+        mPublicProxy = ConfigurationServicePrx::uncheckedCast(adapter->add(mServant, id));
+        mDirectProxy = ConfigurationServicePrx::uncheckedCast(adapter->createDirectProxy(id));
+        return mDirectProxy;
+    }
 
-        void suspend()
+    void registerFeature(const FileSessionGatewayComponentPtr& gatewayComponent)
+    {
+        assert(gatewayComponent);
+        if (gatewayComponent)
         {
             //
-            // XXX
+            // This should be a public proxy because if we fail over to a
+            // replica, we want the proxy in discovery to be remain generally
+            // valid.
             //
+            gatewayComponent->addFeatureProxyToBackplane(mPublicProxy, 
+                AsteriskSCF::Configuration::FileSessionGateway::V1::ConfigurationDiscoveryCategory);
         }
+        else
+        {
+            mLogger(Error) << "Unable to register configuration service. Provided component reference is nil";
+        }
+    }
+
+    void makeReady(const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& /* locator */,
+        const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr& /* params */)
+    {
+        // XXX
+    }
 
-    private:
+    void suspend()
+    {
         //
-        // These variable names are pretty self-explanatory, so we will let them.
+        // XXX
         //
-        ConfigurationImplPtr mServant; 
-        string mId;
-        ConfigurationServicePrx mPublicProxy;
-        ConfigurationServicePrx mDirectProxy;
-        Logger mLogger;
-    };
-    typedef IceUtil::Handle<ConfigurationFeature> ConfigurationFeaturePtr;
+    }
+
+private:
+    //
+    // These variable names are pretty self-explanatory, so we will let them.
+    //
+    ConfigurationImplPtr mServant; 
+    string mId;
+    ConfigurationServicePrx mPublicProxy;
+    ConfigurationServicePrx mDirectProxy;
+    Logger mLogger;
+};
+
+typedef IceUtil::Handle<ConfigurationFeature> ConfigurationFeaturePtr;
+
 }
 
 AsteriskSCF::FileSessionGtw::ComponentFeaturePtr AsteriskSCF::FileSessionGtw::createConfigurationFeature(
diff --git a/src/Endpoint.cpp b/src/Endpoint.cpp
index ef55780..14ecd81 100644
--- a/src/Endpoint.cpp
+++ b/src/Endpoint.cpp
@@ -392,6 +392,12 @@ public:
         return mSpecification->clone();
     }
 
+    string getName()
+    {
+        SharedLock lock(mLock);
+        return mSpecification->name;
+    }
+
     ReplicationAdapterPtr getReplicationAdapter();
 
     ReplicationAdapterPtr createSessionReplica(
diff --git a/src/Endpoint.h b/src/Endpoint.h
index cb0b6d1..1b8a852 100644
--- a/src/Endpoint.h
+++ b/src/Endpoint.h
@@ -51,6 +51,8 @@ public:
 
     virtual EndpointSpecificationPtr getSpecification() = 0;
 
+    virtual std::string getName() = 0;
+
     virtual ReplicationAdapterPtr getReplicationAdapter() = 0;
 
     virtual ReplicationAdapterPtr createSessionReplica(
diff --git a/src/EndpointSpecification.h b/src/EndpointSpecification.h
index 5d364a9..ee51eab 100644
--- a/src/EndpointSpecification.h
+++ b/src/EndpointSpecification.h
@@ -20,6 +20,7 @@
 #include <vector>
 #include <boost/shared_ptr.hpp>
 #include <ostream>
+#include <AsteriskSCF/Media/File/FileMediaIf.h>
 
 namespace AsteriskSCF
 {
@@ -34,31 +35,55 @@ struct EndpointSpecification
     std::string id;
     std::string name;
     std::string destination;
+    std::string mediaFile;
+    AsteriskSCF::Media::File::V1::FileOperations operations;
 
     static EndpointSpecificationPtr create(const std::string& id, const std::string& name,
-        const std::string& dest)
+        const std::string& dest, const std::string& mediaFileDescription,
+        AsteriskSCF::Media::File::V1::FileOperations ops
+    )
     {
         EndpointSpecificationPtr result(new EndpointSpecification);
         result->id  = id;
         result->name = name;
         result->destination = dest;
+        result->mediaFile = mediaFileDescription;
+        result->operations = ops;
         return result;
     }
 
     EndpointSpecificationPtr clone()
     {
-        return create(id, name, destination);
+        return create(id, name, destination, mediaFile, operations);
     }
 };
 
 inline bool operator==(const EndpointSpecification& lhs, const EndpointSpecification& rhs)
 {
-    return ((lhs.id == rhs.id) && (lhs.name == rhs.name) && (lhs.destination == rhs.destination));
+    return ((lhs.id == rhs.id) && (lhs.name == rhs.name) && (lhs.destination == rhs.destination)
+        && (lhs.mediaFile == rhs.mediaFile) && (lhs.operations == rhs.operations)) ;
 }
 
 inline std::ostream& operator<<(std::ostream& os, const EndpointSpecification& spec)
 {
-    os << "[(id:" << spec.id << "),(name:" << spec.name << "),(destination:" << spec.destination << ")]";
+    os << "[(id:" << spec.id << "),(name:" << spec.name << "),(destination:" << spec.destination << "),(media file:" <<
+        spec.mediaFile << "),(operations:";
+    switch(spec.operations)
+    {
+        case AsteriskSCF::Media::File::V1::Recording:
+            os << "recording";
+            break;
+        case AsteriskSCF::Media::File::V1::Playback:
+            os << "playback";
+            break;
+        case AsteriskSCF::Media::File::V1::Both:
+            os << "both";
+            break;
+        default:
+            os << "error";
+            break;
+    }
+    os <<    ")]";
     return os;
 }
 typedef boost::shared_ptr<EndpointSpecification> EndpointSpecificationPtr;
diff --git a/test/TestEndpointLocator.cpp b/test/TestEndpointLocator.cpp
index b2e1019..b4d0de9 100644
--- a/test/TestEndpointLocator.cpp
+++ b/test/TestEndpointLocator.cpp
@@ -98,9 +98,10 @@ public:
         // interface.
         //
         EndpointSpecificationSeq endpointSpecifications;
-        endpointSpecifications.push_back(EndpointSpecification::create("hello.xyx", "hello world", "helloworld.mka"));
+        endpointSpecifications.push_back(EndpointSpecification::create("hello.xyx", "hello world", "11123",
+                "hello_world.mka", AsteriskSCF::Media::File::V1::Playback));
         endpointSpecifications.push_back(EndpointSpecification::create("busy.circuits.20111020", "circuits are busy",
-                "circuits_r_busy.mka"));
+                "11124", "circuits_are_busy.mka", AsteriskSCF::Media::File::V1::Recording));
         locator->addEndpoints(endpointSpecifications);
 
         EndpointImplSeq endpoints = locator->getEndpoints();
@@ -119,11 +120,11 @@ public:
             for (AsteriskSCF::Core::Routing::V1::RegExSeq::const_iterator iter = destinationList.begin();
                  iter != destinationList.end(); ++iter)
             {
-                if (*iter == "helloworld.mka" )
+                if (*iter == "11123" )
                 {
                     ++helloWorldCheck;
                 }
-                else if (*iter == "circuits_r_busy.mka")
+                else if (*iter == "11124")
                 {
                     ++busyCircuitsCheck;
                 }

commit 99b551bf212cb40f301d4f8b1cd6ae8684e813e1
Author: Brent Eagles <beagles at digium.com>
Date:   Thu Dec 1 11:05:24 2011 -0330

    Many fixes and additional unit tests.

diff --git a/TODO.txt b/TODO.txt
index 07685ef..ad04d36 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -17,3 +17,7 @@
 For tests, see test/TODO.txt
 
 - Analog of connect line info for sessions
+
+- Active components need to populate their replication listener so that
+  a switch to standby has them at close to the same state as any other
+  replica.
diff --git a/src/Endpoint.cpp b/src/Endpoint.cpp
index 216f920..ef55780 100644
--- a/src/Endpoint.cpp
+++ b/src/Endpoint.cpp
@@ -90,19 +90,29 @@ public:
         mSpecification(endpointSpecification), 
         mAdapter(adapterForCreatingSessions),
         mPublicProxy(myAllegedProxy),
-        mLogger(logger)
+        mLogger(logger),
+        mDestroyed(false)
     {
         mCookieManager.reset(new CookieManager(
                 CookieManagerListenerPtr(new CookieManagerCallbackAdapter(this))));
     }
 
-    SessionPrx createSession(const string& /* "destination" is irrelevant here */,
+    SessionPrx createSession(const string& destination,
         const SessionListenerPrx& listener,
         const AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookPrx& hook, 
         const Ice::Current& current)
     {
+        {
+            SharedLock lock(mLock);
+            if (destination != mSpecification->destination)
+            {
+                mLogger(Warning) << "Creating a session with a destination that does not match "
+                                 << "the configured destination.";
+            }
+        }
+        
         //
-        // TODO: support for session creation hook.
+        // TODO: complete support for session creation hook.
         //
         string baseId = current.adapter->getCommunicator()->identityToString(current.id);
         baseId += ".ascf_file_session." + IceUtil::generateUUID();
@@ -324,6 +334,18 @@ public:
         return mSpecification->id;
     }
 
+    bool isDestroyed()
+    {
+        SharedLock lock(mLock);
+        return mDestroyed;
+    }
+
+    void destroy()
+    {
+        UniqueLock lock(mLock);
+        mDestroyed = true;
+    }
+
     void destroySession(const SessionPrx& sessionToDestroy)
     {
         //
@@ -367,11 +389,7 @@ public:
     EndpointSpecificationPtr getSpecification()
     {
         SharedLock lock(mLock);
-        
-        EndpointSpecificationPtr spec(new EndpointSpecification);
-        spec->id = mSpecification->id;
-        spec->destination = mSpecification->destination;
-        return spec;
+        return mSpecification->clone();
     }
 
     ReplicationAdapterPtr getReplicationAdapter();
@@ -403,13 +421,6 @@ public:
         return createSessionReplica(newSession, Replication::StateItemSeq());
     }
 
-    void destroy()
-    {
-        //
-        // todo.
-        //
-    }
-
 protected:
 
     void onProxyUpdate()
@@ -447,6 +458,7 @@ private:
     AsteriskSCF::SessionCommunications::V1::SessionEndpointPrx mPublicProxy;
     
     Logger mLogger;
+    bool mDestroyed;
 
     boost::shared_mutex mLock;
 
diff --git a/src/Endpoint.h b/src/Endpoint.h
index 8897a1e..cb0b6d1 100644
--- a/src/Endpoint.h
+++ b/src/Endpoint.h
@@ -34,6 +34,9 @@ class EndpointImpl : public AsteriskSCF::SessionCommunications::V1::SessionEndpo
 public:
 
     EndpointImpl(const std::string& id);
+
+    virtual bool isDestroyed() = 0;
+    virtual void destroy() = 0;
     
     /**
      *
diff --git a/src/EndpointLocator.cpp b/src/EndpointLocator.cpp
index 8f357de..0be9c3f 100644
--- a/src/EndpointLocator.cpp
+++ b/src/EndpointLocator.cpp
@@ -197,6 +197,7 @@ public:
         EndpointLocatorImpl(id + ".EndpointLocator"),
         mEndpointAdapter(adapter),
         mLogger(logger),
+        mId(id + ".EndpointLocator"),
         mDestroyed(false)
     {
     }
@@ -269,68 +270,77 @@ public:
 
     void removeEndpoints(const EndpointSpecificationSeq& endpoints)
     {
-        UniqueLock lock(mLock);
-
-        for (EndpointSpecificationSeq::const_iterator iter = endpoints.begin();
-            iter != endpoints.end(); ++iter)
+        EndpointImplSeq removedEndpoints;
         {
-            EndpointMap::iterator endpointEntry = mEndpoints.find((*iter)->id);
-            if (endpointEntry != mEndpoints.end())
+            UniqueLock lock(mLock);
+
+            for (EndpointSpecificationSeq::const_iterator iter = endpoints.begin();
+                 iter != endpoints.end(); ++iter)
             {
-                //
-                // Undo index entry.. but I'm not at all sure we can rely
-                // on the destination being correct, better to find it by
-                // way of checking the values.
-                //
-                for (DestinationIndex::iterator indexEntry = mIndex.begin();
-                    indexEntry != mIndex.end() ; ++indexEntry)
+                string key = EndpointIdPrefix + (*iter)->id;
+                EndpointMap::iterator endpointEntry = mEndpoints.find(key);
+                if (endpointEntry != mEndpoints.end())
                 {
-                    if (indexEntry->second == (*iter)->id)
+                    //
+                    // Undo index entry.. but I'm not at all sure we can rely
+                    // on the destination being correct, better to find it by
+                    // way of checking the values.
+                    //
+                    for (DestinationIndex::iterator indexEntry = mIndex.begin();
+                         indexEntry != mIndex.end() ; ++indexEntry)
                     {
-                        string destination = indexEntry->first;
-                        //
-                        // TODO: it might be nice to put a little
-                        // defensive check in here.
-                        //
-                        mIndex.erase(destination);
-
-                        //
-                        // Keep going in case we have multiple destinations
-                        // mapping to this Endpoint (i.e. alias). I know
-                        // this might be weird but I cannot think of
-                        // a good reason to disallow it for file sessions.
-                        //
+                        if (indexEntry->second == (*iter)->id)
+                        {
+                            string destination = indexEntry->first;
+                            //
+                            // TODO: it might be nice to put a little
+                            // defensive check in here.
+                            //
+                            mIndex.erase(destination);
+
+                            //
+                            // Keep going in case we have multiple destinations
+                            // mapping to this Endpoint (i.e. alias). I know
+                            // this might be weird but I cannot think of
+                            // a good reason to disallow it for file sessions.
+                            //
+                        }
+                    }
+                    //
+                    // Now let's remove the servant from the object adapter, 
+                    // this has the nice effect of causing any calls that haven't
+                    // already been dispatched on the servant to fail with
+                    // ONE's. 
+                    //
+                    string idString = EndpointIdPrefix + (*iter)->id;
+                    Ice::Identity id = 
+                        mEndpointAdapter->getCommunicator()->stringToIdentity(idString);
+                    try
+                    {
+                        mEndpointAdapter->remove(id);
+                    }
+                    catch (const Ice::Exception& ex)
+                    {
+                        mLogger(Error) << "Unexpected exception when deactivating " << idString << ": " << ex.what();
+                    }
+                    catch (...)
+                    {
+                        mLogger(Error) << "Unknown exception when deactivating " << idString;
                     }
-                }
-                //
-                // Now let's remove the servant from the object adapter, 
-                // this has the nice effect of causing any calls that haven't
-                // already been dispatched on the servant to fail with
-                // ONE's. 
-                //
-                string idString = EndpointIdPrefix + (*iter)->id;
-                Ice::Identity id = 
-                    mEndpointAdapter->getCommunicator()->stringToIdentity(idString);
-                try
-                {
-                    mEndpointAdapter->remove(id);
-                }
-                catch (const Ice::Exception& ex)
-                {
-                    mLogger(Error) << "Unexpected exception when deactivating " << idString << ": " << ex.what();
-                }
-                catch (...)
-                {
-                    mLogger(Error) << "Unknown exception when deactivating " << idString;
-                }
 
-                //
-                // After this... the only reference counts left to that endpoint
-                // should be for any pending upcalls.
-                //
-                mEndpoints.erase(endpointEntry);
+                    //
+                    // After this... the only reference counts left to that endpoint
+                    // should be for any pending upcalls.
+                    //
+                    removedEndpoints.push_back(endpointEntry->second);
+                    mEndpoints.erase(endpointEntry);
+                }
             }
         }
+        for (EndpointImplSeq::const_iterator iter = removedEndpoints.begin(); iter != removedEndpoints.end(); ++iter)
+        {
+            (*iter)->destroy();
+        }
     }
 
     RegExSeq getDestinationList() 
@@ -364,12 +374,6 @@ public:
         return impls;
     }
 
-    void setId(const string& id)
-    {
-        UniqueLock lock(mLock);
-        mId = id;
-    }
-
     string getId()
     {
         SharedLock lock(mLock);
diff --git a/src/EndpointLocator.h b/src/EndpointLocator.h
index a4bc13a..b564fad 100644
--- a/src/EndpointLocator.h
+++ b/src/EndpointLocator.h
@@ -39,10 +39,14 @@ class EndpointLocatorImpl : public AsteriskSCF::Core::Routing::V1::EndpointLocat
 {
 public:
 
+    /**
+     * Sadly, this constructor only exists to pass an id to the
+     * ReplicatedObject base class.
+     */
     EndpointLocatorImpl(const std::string& id);
     
     /**
-     * Called by configuration/replication. Add and possibly create an 
+     * Called by configuration/replication. Add and possibly create an
      * endpoint to the locator.
      */
     virtual void addEndpoints(const EndpointSpecificationSeq&) = 0;
diff --git a/src/EndpointSpecification.h b/src/EndpointSpecification.h
index ab25670..5d364a9 100644
--- a/src/EndpointSpecification.h
+++ b/src/EndpointSpecification.h
@@ -19,18 +19,48 @@
 #include <string>
 #include <vector>
 #include <boost/shared_ptr.hpp>
+#include <ostream>
 
 namespace AsteriskSCF
 {
 namespace FileSessionGtw
 {
+
+struct EndpointSpecification;
+typedef boost::shared_ptr<EndpointSpecification> EndpointSpecificationPtr;
+
 struct EndpointSpecification 
 {
     std::string id;
     std::string name;
     std::string destination;
+
+    static EndpointSpecificationPtr create(const std::string& id, const std::string& name,
+        const std::string& dest)
+    {
+        EndpointSpecificationPtr result(new EndpointSpecification);
+        result->id  = id;
+        result->name = name;
+        result->destination = dest;
+        return result;
+    }
+
+    EndpointSpecificationPtr clone()
+    {
+        return create(id, name, destination);
+    }
 };
 
+inline bool operator==(const EndpointSpecification& lhs, const EndpointSpecification& rhs)
+{
+    return ((lhs.id == rhs.id) && (lhs.name == rhs.name) && (lhs.destination == rhs.destination));
+}
+
+inline std::ostream& operator<<(std::ostream& os, const EndpointSpecification& spec)
+{
+    os << "[(id:" << spec.id << "),(name:" << spec.name << "),(destination:" << spec.destination << ")]";
+    return os;
+}
 typedef boost::shared_ptr<EndpointSpecification> EndpointSpecificationPtr;
 typedef std::vector<EndpointSpecificationPtr> EndpointSpecificationSeq;
 
diff --git a/src/FileSessionGatewayReplicator.cpp b/src/FileSessionGatewayReplicator.cpp
new file mode 100644
index 0000000..85dae23
--- /dev/null
+++ b/src/FileSessionGatewayReplicator.cpp
@@ -0,0 +1,218 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010-2011, 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 <Ice/Ice.h>
+#include <IceBox/IceBox.h>
+
+#include <AsteriskSCF/Logger/IceLogger.h>
+#include <AsteriskSCF/logger.h>
+#include <AsteriskSCF/Core/Discovery/ServiceLocatorIf.h>
+#include <AsteriskSCF/Replication/FileSessionGateway/FileSessionReplicationIf.h>
+#include <AsteriskSCF/Replication/StateReplicator.h>
+#include <AsteriskSCF/Discovery/LocatorRegistrationWrapper.h>
+
+using namespace AsteriskSCF::System::Logging;
+using namespace AsteriskSCF::SessionCommunications::V1;
+using namespace AsteriskSCF::Core::Discovery::V1;
+using namespace AsteriskSCF::Replication::FileSessionGateway::V1;
+using namespace AsteriskSCF;
+using namespace AsteriskSCF::Discovery;
+using namespace std;
+
+typedef AsteriskSCF::Replication::StateReplicator<
+    AsteriskSCF::Replication::FileSessionGateway::V1::StateReplicator,
+    AsteriskSCF::Replication::FileSessionGateway::V1::StateItemPtr,
+    string,
+    AsteriskSCF::Replication::FileSessionGateway::V1::StateReplicatorListenerPrx> ReplicatorI;
+
+typedef IceUtil::Handle<ReplicatorI> ReplicatorIPtr;
+
+namespace
+{
+Logger lg = getLoggerFactory().getLogger("AsteriskSCF.FileSessionGatewayReplicator");
+}
+
+namespace
+{
+
+class FileSessionGatewayReplicatorApp : public IceBox::Service
+{
+public:
+    FileSessionGatewayReplicatorApp();
+
+protected:
+    void start(const string& name, const Ice::CommunicatorPtr& communicator, const Ice::StringSeq& args);
+    void stop();
+
+private:
+    /**
+     * A proxy to the service locator manager for the file session gateway replicator service.
+     */
+    LocatorRegistrationWrapperPtr mLocator;
+    Ice::ObjectAdapterPtr mAdapter;
+    RegisterThreadPtr mRegisterThread; 
+    ReplicatorIPtr mReplicator;
+};
+
+FileSessionGatewayReplicatorApp::FileSessionGatewayReplicatorApp()
+{
+}
+
+void FileSessionGatewayReplicatorApp::start(const string& name, const Ice::CommunicatorPtr& communicator,
+    const Ice::StringSeq&)
+{
+    Logger logger = getLoggerFactory().getLogger("AsteriskSCF.FileSessionGatewayReplicator");
+    logger(Debug) << "Launching AsteriskSCF FileSessionGateway Replicator Service." ;
+
+    //
+    // It is standard practice to base the adapter name on the configured
+    // service instance name.
+    //
+    string adapterName;
+    if(name.size() == 0)
+    {
+        adapterName = "Adapter";
+    }
+    else
+    {
+        adapterName = name + ".Adapter";
+    }
+
+    //
+    // Check on the threadpool properties, make sure that they are compatible with the requirements of this 
+    // service. This could be moved into a helper method, but it is somehow more clear for seeing what
+    // is going on during initialization to leave it here.
+    //
+    // TODO: Are there any other properties that need to be double-checked before proceeding?
+    //
+    Ice::Int defaultPoolSize =
+        communicator->getProperties()->getPropertyAsIntWithDefault("Ice.ThreadPool.Server.Size", 0);
+    if (communicator->getProperties()->getPropertyAsIntWithDefault(adapterName + ".ThreadPool.Size", 0) < 4)
+    {
+        if (defaultPoolSize < 4)
+        {
+            logger(Info) << "Configured thread pool size for " << adapterName + " is too small, defaulting to 4";
+            communicator->getProperties()->setProperty(adapterName + ".ThreadPool.Size", "4");
+        }
+    }
+
+    //
+    // TODO: All adapter ids should be globally unique. This would allow replicas to be identified.
+    // How this might be useful is that it might be used as a replicated state item to identify
+    // which adapter is currently the primary in a group of replicas.
+    //
+    mAdapter = communicator->createObjectAdapterWithEndpoints(adapterName,
+        communicator->getProperties()->getPropertyWithDefault(adapterName + ".Endpoints", "default"));
+
+    //
+    // Configure the AsteriskSCF logger.
+    // TODO: check whether this works right if we've already created the logger object.
+    //
+    ConfiguredIceLoggerPtr iceLogger = createIceLogger(mAdapter);
+    getLoggerFactory().setLogOutput(iceLogger->getLogger());
+
+
+    string property = communicator->getProperties()->getProperty("LocatorServiceManagement.Proxy");
+    if(property.size() == 0)
+    {
+        throw IceBox::FailureException(__FILE__, __LINE__,
+                "Configuration error: Unable to locate property `LocatorServiceManagement.Proxy'");
+    }
+    
+    //
+    // TODO: The bridge manager's identity should come from a central configuration and/or a replicator
+    // service.
+    //
+    string managerName = "FileSessionGatewayReplicator";
+    mReplicator = new ReplicatorI;
+    StateReplicatorPrx replicatorPrx =
+        StateReplicatorPrx::uncheckedCast(mAdapter->add(mReplicator, communicator->stringToIdentity(managerName)));
+
+    assert(replicatorPrx != 0);
+    if(replicatorPrx == 0)
+    {
+        throw IceBox::FailureException(__FILE__, __LINE__, "Unable to instantiate bridge replicator object");
+    }
+
+    bool registered = false;
+    try
+    {
+        std::string serviceName = communicator->getProperties()->getPropertyWithDefault(
+          name + ".ServiceName", "default");
+
+        ServiceLocatorParamsPtr locatorParameters = new ServiceLocatorParams;
+        //
+        // Category is specified with full scope to avoid problems with namespaces.
+        //
+        locatorParameters->category =
+            AsteriskSCF::Replication::FileSessionGateway::V1::StateReplicatorDiscoveryCategory;
+        locatorParameters->service = serviceName;
+        locatorParameters->id = communicator->getProperties()->getPropertyWithDefault(name + ".StateReplicatorId",
+                "default");
+        mLocator = new LocatorRegistrationWrapper(communicator, property, replicatorPrx,
+            adapterName, locatorParameters);
+        registered = mLocator->registerService();
+    }
+    catch(const Ice::Exception& e)
+    {
+        lg(Error) << "Exception starting bridge replicator: " << e.what();
+        throw;
+    }
+
+    if(!registered)
+    {
+        mRegisterThread = new RegisterThread(mLocator);
+        mRegisterThread->start();
+    }
+    //
+    // TODO: We need to know whether or not to activate!
+    //
+    mAdapter->activate();
+}
+
+void FileSessionGatewayReplicatorApp::stop()
+{
+    if(mRegisterThread)
+    {
+        mRegisterThread->stop();
+    }
+    try
+    {
+        mLocator->unregister();
+    }
+    catch(const Ice::Exception&)
+    {
+    }
+    try
+    {
+        Ice::CommunicatorPtr comm = mAdapter->getCommunicator();
+        comm->shutdown();
+        mAdapter->waitForDeactivate();
+        comm->destroy();
+    }
+    catch(...)
+    {
+        // TODO: log
+    }
+}
+}
+
+extern "C" {
+ASTSCF_DLL_EXPORT ::IceBox::Service* create(Ice::CommunicatorPtr)
+{
+    return new FileSessionGatewayReplicatorApp;
+}
+}
diff --git a/src/ReplicationListener.cpp b/src/ReplicationListener.cpp
index 831455c..6842afc 100644
--- a/src/ReplicationListener.cpp
+++ b/src/ReplicationListener.cpp
@@ -38,7 +38,6 @@ typedef map<string, ReplicationAdapterPtr> ReplicatedObjectAdapterMap;
 class StateReplicatorListenerImpl : public ReplicationListener
 {
 public:
-
     StateReplicatorListenerImpl(const EndpointLocatorImplPtr& endpointLocator, 
         const Logger& logger) :
         mDestroyed(false),
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index bc99000..22d4a27 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -24,3 +24,25 @@ astscf_component_add_boost_libraries(FileSessionGatewaySessionTest unit_test_fra
 astscf_component_build_standalone(FileSessionGatewaySessionTest)
 target_link_libraries(FileSessionGatewaySessionTest logging-client astscf-ice-util-cpp)
 astscf_test_boost(FileSessionGatewaySessionTest)
+
+astscf_component_init(FileSessionGatewayEndpointLocatorTest)
+astscf_component_add_files(FileSessionGatewayEndpointLocatorTest
+	../src/ComponentDefs.h
+	../src/LoggerF.h
+	../src/CookieManager.h
+	../src/CookieManager.cpp
+	../src/ReplicationAdapter.h
+	../src/ReplicatedObject.cpp
+	../src/ReplicatedObject.h
+	../src/Endpoint.h
+	../src/Endpoint.cpp
+	../src/Session.h
+	../src/Session.cpp
+	TestEndpointLocator.cpp
+	)
+astscf_component_add_slice_collection_libraries(FileSessionGatewayEndpointLocatorTest
+    FILESESSIONGATEWAY ASTSCF)
+astscf_component_add_boost_libraries(FileSessionGatewayEndpointLocatorTest unit_test_framework thread)
+astscf_component_build_standalone(FileSessionGatewayEndpointLocatorTest)
+target_link_libraries(FileSessionGatewayEndpointLocatorTest logging-client astscf-ice-util-cpp)
+astscf_test_boost(FileSessionGatewayEndpointLocatorTest)
diff --git a/test/TestEndpointLocator.cpp b/test/TestEndpointLocator.cpp
new file mode 100644
index 0000000..b2e1019
--- /dev/null
+++ b/test/TestEndpointLocator.cpp
@@ -0,0 +1,232 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2011, 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.
+ */
+
+/**
+ *
+ * This test drive is very "unit testing" oriented. With very direct
+ * exercising of interfaces. No collateral services are employed by these
+ * tests, so it may be run standalone.
+ *
+ */
+
+//
+// boost does something here that VC++ complains loudly and annoyingly about
+//
+#ifdef WIN32
+#pragma warning(disable: 4996)
+#endif
+
+#define BOOST_TEST_NO_MAIN
+
+#include <boost/test/unit_test.hpp>
+#include <boost/test/debug.hpp>
+#include <boost/bind.hpp>
+
+#include <Ice/Ice.h>
+
+//
+// We need to include the source file itself to get access to the implementation details.
+//
+#include "../src/EndpointLocator.cpp"
+
+using namespace AsteriskSCF::System::Logging;
+using namespace std;
+using namespace boost::unit_test;
+using namespace AsteriskSCF::FileSessionGtw;
+
+class EndpointLocatorTestSuite
+{
+public:
+    EndpointLocatorTestSuite(const Ice::CommunicatorPtr& communicator, const Ice::ObjectAdapterPtr& adapter,
+        const Logger& logger) :
+        mCommunicator(communicator),
+        mObjectAdapter(adapter),
+        mLogger(logger)
+    {
+    }
+
+    //
+    // Helper function for creating a test EndpointLocator object instance.
+    //
+    EndpointLocatorServantPtr createTestEndpointLocator(const string& id)
+    {
+        return new EndpointLocatorServant(id, mObjectAdapter, mLogger);
+    }
+
+    //
+    // Exercise the methods declared in EndpointLocator.h.
+    //
+    void implementationInterfaceTests()
+    {
+        EndpointLocatorServantPtr locator = createTestEndpointLocator("TestEndpointLocator");
+        BOOST_CHECK(locator->getId() == "TestEndpointLocator.EndpointLocator");
+
+        //
+        // For the moment the endpoint locator does not have a replication adapter. Endpoints
+        // are replicated by way of configuration replication.
+        //
+        AsteriskSCF::FileSessionGtw::ReplicationAdapterPtr replicationAdapter =
+            locator->getReplicationAdapter();
+        BOOST_CHECK(!replicationAdapter);
+
+        //
+        // Check to make sure the proxy is stored and retrievable.
+        // 
+        Ice::Identity locatorIdentity = mCommunicator->stringToIdentity("TestEndpointLocator");
+        locator->setProxy(AsteriskSCF::Core::Routing::V1::EndpointLocatorPrx::uncheckedCast(
+                mObjectAdapter->createProxy(locatorIdentity)));
+        AsteriskSCF::Core::Routing::V1::EndpointLocatorPrx locatorPrx =
+            locator->getProxy();
+        BOOST_REQUIRE(locatorPrx);
+        BOOST_CHECK(locatorPrx->ice_getIdentity() == locatorIdentity);
+
+        //
+        // See if we can create some test endpoints using the internal
+        // interface.
+        //
+        EndpointSpecificationSeq endpointSpecifications;
+        endpointSpecifications.push_back(EndpointSpecification::create("hello.xyx", "hello world", "helloworld.mka"));
+        endpointSpecifications.push_back(EndpointSpecification::create("busy.circuits.20111020", "circuits are busy",
+                "circuits_r_busy.mka"));
+        locator->addEndpoints(endpointSpecifications);
+
+        EndpointImplSeq endpoints = locator->getEndpoints();
+        
+        //
+        // This is a require instead of a check because the sequence is
+        // used for tests later on.
+        //
+        BOOST_REQUIRE(endpoints.size() == 2);
+
+        AsteriskSCF::Core::Routing::V1::RegExSeq destinationList = locator->getDestinationList();
+        BOOST_CHECK(destinationList.size() == 2);
+        int helloWorldCheck = 0;
+        int busyCircuitsCheck = 0;
+        {
+            for (AsteriskSCF::Core::Routing::V1::RegExSeq::const_iterator iter = destinationList.begin();
+                 iter != destinationList.end(); ++iter)
+            {
+                if (*iter == "helloworld.mka" )
+                {
+                    ++helloWorldCheck;
+                }
+                else if (*iter == "circuits_r_busy.mka")
+                {
+                    ++busyCircuitsCheck;
+                }
+            }
+        }
+        BOOST_CHECK(helloWorldCheck == 1);
+        BOOST_CHECK(busyCircuitsCheck == 1);
+
+        //
+        // We need to examine the endpoints created through
+        // EndpointLocator::addEndpoints to better validate the proper
+        // operation of that call.
+        //
+        EndpointImplPtr endpointA = endpoints[0];
+        EndpointImplPtr endpointB = endpoints[1];
+        EndpointSpecificationPtr specA = endpointA->getSpecification();
+        EndpointSpecificationPtr specB = endpointB->getSpecification();
+
+        //
+        // We want to hold on to the endpoints according to the
+        // the specifications that were used to create them.
+        //
+        EndpointImplPtr endpointForFirstSpec;
+        EndpointImplPtr endpointForSecondSpec;
+        if (specA->id == endpointSpecifications[0]->id)
+        {
+            endpointForFirstSpec = endpointA;
+            endpointForSecondSpec = endpointB;;
+            BOOST_CHECK(*specA == *(endpointSpecifications[0]));
+            BOOST_CHECK(*specB == *(endpointSpecifications[1]));
+        }
+        else if(specA->id == endpointSpecifications[1]->id)
+        {
+            endpointForFirstSpec = endpointB;
+            endpointForSecondSpec = endpointA;;
+            BOOST_CHECK(*specA == *(endpointSpecifications[1]));
+            BOOST_CHECK(*specB == *(endpointSpecifications[0]));
+        }
+        else
+        {
+            BOOST_FAIL("The endpoint specifications for the generated endpoints do not match"
+                " the endpoint specifications provided");
+        }
+
+        EndpointSpecificationPtr leftOverEndpointSpec = endpointSpecifications.front();
+        endpointSpecifications.erase(endpointSpecifications.begin());
+        locator->removeEndpoints(endpointSpecifications);
+        endpoints = locator->getEndpoints();
+        BOOST_REQUIRE(endpoints.size() == 1);
+        BOOST_CHECK(*(endpoints[0]->getSpecification()) == *leftOverEndpointSpec);
+        BOOST_CHECK(!endpointForFirstSpec->isDestroyed());
+        BOOST_CHECK(endpointForSecondSpec->isDestroyed());
+        BOOST_CHECK(*(endpointForFirstSpec->getSpecification()) == *leftOverEndpointSpec);
+
+        //
+        // Yay. Add and remove of endpoint specifications works at this level. As long as
+        // config does the right thing in creating the specs, all is well.
+        //
+    }
+
+    
+private:
+    Ice::CommunicatorPtr mCommunicator;
+    Ice::ObjectAdapterPtr mObjectAdapter;
+    AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx mLocator;
+    Logger mLogger;
+};
+
+boost::shared_ptr<EndpointLocatorTestSuite> endpointLocatorSuite;
+
+bool init_unit_test()
+{
+    framework::master_test_suite().add(BOOST_TEST_CASE(
+            boost::bind(&EndpointLocatorTestSuite::implementationInterfaceTests, endpointLocatorSuite)));
+
+    return true;
+}
+
+int main(int argc, char** argv)
+{
+    Logger logger(getLoggerFactory().getLogger("AsteriskSCF.UnitTest.FileSessionGateway.EndpointLocator"));
+    try
+    {
+        Ice::CommunicatorPtr communicator = Ice::initialize(argc, argv);
+        Ice::ObjectAdapterPtr objectAdapter = communicator->createObjectAdapterWithEndpoints(
+            "UnitTestAdapter", communicator->getProperties()->getPropertyWithDefault(
+                "UnitTestAdapter.Endpoints", "default"));
+        objectAdapter->activate();
+        //
+        // Initialize test suite objects.
+        //
+        endpointLocatorSuite.reset(new EndpointLocatorTestSuite(communicator, objectAdapter, logger));
+        return unit_test_main(&init_unit_test, argc, argv);
+    }
+    catch (const std::exception& ex)
+    {
+        logger(Error) << "Unexpected " << ex.what() << " caught in main. Tests in " << argv[0] << " have failed!";
+        return EXIT_FAILURE;
+    }
+    catch (...)
+    {
+        logger(Error) << "Unknown exception caught in main. Tests in " << argv[0] << " have failed!";
+        return EXIT_FAILURE;
+    }
+    return EXIT_SUCCESS;
+}
diff --git a/test/TestSessionObject.cpp b/test/TestSessionObject.cpp
index 3802851..1639f87 100644
--- a/test/TestSessionObject.cpp
+++ b/test/TestSessionObject.cpp
@@ -275,7 +275,6 @@ public:
         mObjectAdapter(adapter),
         mLogger(logger)
     {
-        cerr << mCommunicator->getProperties()->getProperty("LocatorService.Proxy") << endl;
         mLocator = AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx::uncheckedCast(
             mCommunicator->propertyToProxy("LocatorService.Proxy"));
         //
@@ -527,11 +526,12 @@ public:
             BOOST_CHECK("cookie updates appear to have processed correctly");
 
             //
-            // TODO: the rest of the state updates.
-            // SessionListener.
-            // SessionController.
-            // MediaSession.
-            // Streams.
+            // TODO: the rest of the state updates:
+            //
+            // * SessionListener.
+            // * SessionController.
+            // * MediaSession.
+            // * Streams.
             //
         }
         catch (const std::exception& ex)

commit 08e0374f2d8df503f5e1765d62a52c0ce7c58102
Author: Brent Eagles <beagles at digium.com>
Date:   Wed Nov 30 16:29:48 2011 -0330

    Fixup multitude of build errors after replication refactor.

diff --git a/CMakeLists.txt b/CMakeLists.txt
index dd29684..f07ab19 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,7 +1,7 @@
 astscf_project(FileSessionGateway 3.4)
 
 add_subdirectory(slice)
-# add_subdirectory(src)
+add_subdirectory(src)
 add_subdirectory(test)
 
 #
diff --git a/TODO.txt b/TODO.txt
new file mode 100644
index 0000000..07685ef
--- /dev/null
+++ b/TODO.txt
@@ -0,0 +1,19 @@
+#
+# Asterisk SCF -- An open-source communications framework.
+#
+# Copyright (C) 2011, 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.
+# 
+
+For tests, see test/TODO.txt
+
+- Analog of connect line info for sessions
diff --git a/config/FileSessionGatewayConfigurator.py b/config/FileSessionGatewayConfigurator.py
index 3da565e..e5f8966 100755
--- a/config/FileSessionGatewayConfigurator.py
+++ b/config/FileSessionGatewayConfigurator.py
@@ -26,357 +26,54 @@ Ice.loadSlice("--underscore -I\"" + os.environ["ASTSCF_HOME"] + "\"" + " -I" + I
 import AsteriskSCF.Configuration.FileSessionGateway.V1
 
 # Add our own visitor implementations for the sections we support
-class SipSectionVisitors(Configurator.SectionVisitors):
-    def visit_general(self, config, section):
-        group = AsteriskSCF.Configuration.SipSessionManager.V1.SipGeneralGroup()
-        group.configurationItems = { }
-        self.groups.append(group)
+class SectionVisitors(Configurator.SectionVisitors):
 
-    def visit_transport_udp(self, config, section):
-        group = AsteriskSCF.Configuration.SipSessionManager.V1.SipUDPTransportGroup()
-        group.name = section
+    def visit_general_group(self, config, section):
+        group = AsteriskSCF.Configuration.FileSessionGateway.V1.GeneralGroup()
         group.configurationItems = { }
-
-        mapper = Configurator.OptionMapper()
-        item = AsteriskSCF.Configuration.SipSessionManager.V1.SipHostItem()
-        mapper.map('host', item, 'host', 'address', config.get, None)
-        mapper.map('port', item, 'port', 'address', config.getint, 5060)
-        for option in config.options(section):
-            mapper.execute(group, section, option)
-
-        mapper.finish(group)
-
+        # no current configuration items.
         self.groups.append(group)
-
-    def visit_transport_tcp(self, config, section):
-        group = AsteriskSCF.Configuration.SipSessionManager.V1.SipTCPTransportGroup()
-        group.name = section
+        
+    def visit_endpoint_group(self, config, section):
+        #
+        # setup endpoint group.
+        #
+        group = AsteriskSCF.Configuration.FileSessionGateway.V1.EndpointGroup()
         group.configurationItems = { }
 
-        mapper = Configurator.OptionMapper()
-        item = AsteriskSCF.Configuration.SipSessionManager.V1.SipHostItem()
-        mapper.map('host', item, 'host', 'address', config.get, None)
-        mapper.map('port', item, 'port', 'address', config.getint, 5060)
-        for option in config.options(section):
-            mapper.execute(group, section, option)
-
-        mapper.finish(group)
-
-        self.groups.append(group)
-
-    def visit_transport_tls(self, config, section):
-        group = AsteriskSCF.Configuration.SipSessionManager.V1.SipTLSTransportGroup()
-        group.name = section
-        group.configurationItems = { }
-
-        mapper = Configurator.OptionMapper()
-        item = AsteriskSCF.Configuration.SipSessionManager.V1.SipHostItem()
-        mapper.map('host', item, 'host', 'address', config.get, None)
-        mapper.map('port', item, 'port', 'address', config.getint, 5060)
-        for option in config.options(section):
-            mapper.execute(group, section, option)
-
-        mapper.finish(group)
-
-        self.groups.append(group)
-
-    def visit_transport_stun(self, config, section):
-        group = AsteriskSCF.Configuration.SipSessionManager.V1.SipSTUNTransportGroup()
-        group.name = section
-        group.configurationItems = {}
-        mapper = Configurator.OptionMapper()
-
-        item = AsteriskSCF.Configuration.SipSessionManager.V1.SipSignalingSTUNHostItem()
-        mapper.map('stunhost', item, 'address', 'stunServer', config.get, None)
-        mapper.map('stunport', item, 'port', 'stunServer', config.getint, 3478)
-
-        item = AsteriskSCF.Configuration.SipSessionManager.V1.SipHostItem()
-        mapper.map('baseaddress', item, 'host', 'baseAddress', config.get, None)
-        mapper.map('baseport', item, 'port', 'baseAddress', config.getint, 4512)
-
-        for option in config.options(section):
-            mapper.execute(group, section, option)
-
-        mapper.finish(group)
-
-        self.groups.append(group)
-
-    def visit_registration(self, config, section):
-
-        class RegistrationContactHandler:
+        #
+        # process config.
+        #
+        class FileOperationTransformer():
             def __init__(self, config):
                 self.config = config
-            def get(self, section, option):
-                setting = config.get(section, option)
-                contacts = setting.split(',')
-                ret = []
-
-                for contact in contacts:
-                    uri, slash, expiration = contact.partition('/')
-                    info = AsteriskSCF.Configuration.SipSessionManager.V1.ContactInfo()
-                    info.contactURI = uri
-                    info.expiration = int(expiration)
-                    ret.append(info)
-
-                return ret
-
-        group = AsteriskSCF.Configuration.SipSessionManager.V1.SipRegistrationGroup()
-        group.name = section
-        group.configurationItems = {}
 
-        mapper = Configurator.OptionMapper()
-
-        item = AsteriskSCF.Configuration.SipSessionManager.V1.SipClientRegistrationItem()
-
-        mapper.map('aor', item, 'aor', 'registration', config.get, None)
-        mapper.map('expiration', item, 'defaultExpiration', 'registration', config.getint, AsteriskSCF.Configuration.SipSessionManager.V1.DefaultRegistrationExpirationSeconds)
-        handler = RegistrationContactHandler(config)
-        mapper.map('contacts', item, 'contacts', 'registration', handler.get, None)
-
-        for option in config.options(section):
-            mapper.execute(group, section, option)
-
-        mapper.finish(group)
-
-        self.groups.append(group)
-
-    def visit_identity(self, config, section):
-        group = AsteriskSCF.Configuration.SipSessionManager.V1.IdentityGroup()
-        group.name = section
-        group.configurationItems = { }
-
-        mapper = Configurator.OptionMapper()
-
-        item =  AsteriskSCF.Configuration.SipSessionManager.V1.IdentityItem()
-	#      map(option, object, item, item_name, method, default)
-        mapper.map('name', item, 'name', 'id', config.get, None)
-        mapper.map('number', item, 'number', 'id', config.get, None)
-
-        for option in config.options(section):
-            mapper.execute(group, section, option)
-
-        mapper.finish(group)
-
-        self.groups.append(group)
-
-    def visit_endpoint(self, config, section):
-        group = AsteriskSCF.Configuration.SipSessionManager.V1.SipEndpointGroup()
-        group.name = section
-        group.configurationItems = { }
-
-        mapper = Configurator.OptionMapper()
-
-        mapper.map('routing', AsteriskSCF.Configuration.SipSessionManager.V1.SipRoutingItem(), 'routingServiceName', 'routingService', config.get, None)
-
-        item = AsteriskSCF.Configuration.SipSessionManager.V1.IdentityItem()
-        mapper.map('name', item, 'name', 'identity', config.get, None)
-        mapper.map('number', item, 'number', 'identity', config.get, None)
-
-        # Alternate form of setting id is a list of references to IdentityGroup objects.
-	try:
-            ids = config.get(section, 'ids')
-            idList = ids.split(',')
-            for id in idList:
-                item = AsteriskSCF.Configuration.SipSessionManager.V1.IdentityGroupRef()
-                item.identityGroupName = id
-                group.configurationItems[id] = item
-	except ConfigParser.NoOptionError:
-	    # It's legit to omit the ids option from this section.
-	    pass
-
-        item = AsteriskSCF.Configuration.SipSessionManager.V1.SipSourceTransportAddressItem()
-        mapper.map('sourcehost', item, 'host', 'sourceaddress', config.get, None)
-        mapper.map('sourceport', item, 'port', 'sourceaddress', config.getint, 5060)
-
-        item = AsteriskSCF.Configuration.SipSessionManager.V1.SipTargetDestinationAddressItem()
-        mapper.map('targethost', item, 'host', 'targetaddress', config.get, None)
-        mapper.map('targetport', item, 'port', 'targetaddress', config.getint, 5060)
-
-        item = AsteriskSCF.Configuration.SipSessionManager.V1.SipSignalingNATItem()
-        mapper.map('enablestun', item, 'stun', 'enableSTUN', config.get, None)
-
-        item = AsteriskSCF.Configuration.SipSessionManager.V1.SipMediaNATItem()
-        mapper.map('enablertpoverice', item, 'enableICE', 'enableRTPICE', config.get, None)
-        mapper.map('enableturn', item, 'enableTURN', 'enableRTPICE', config.get, None)
-
-        item = AsteriskSCF.Configuration.SipSessionManager.V1.SRTPCryptoItem()
-               
-        class CryptoKeyHandler:
-                def __init__(self, config, keyItem):
-                    self.config = config
-                    self.item = keyItem
-
-                def getSuite(self, section, item):
-                    self.item.suite = self.config.get(section, item)
-
-                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)
-
-        class AllowableCallDirectionTransformer():
-            def __init__(self, config):
-                self.config = config
-            def get(self, section, item):
-                if self.config.get(section, item) == 'inbound':
-                    return AsteriskSCF.Configuration.SipSessionManager.V1.SipAllowableCallDirection.Inbound
-                elif self.config.get(section, item) == 'outbound':
-                    return AsteriskSCF.Configuration.SipSessionManager.V1.SipAllowableCallDirection.Outbound
-                elif self.config.get(section, item) == 'both':
-                    return AsteriskSCF.Configuration.SipSessionManager.V1.SipAllowableCallDirection.Both
-                elif self.config.get(section, item) == 'none':
-                    return AsteriskSCF.Configuration.SipSessionManager.V1.SipAllowableCallDirection.Disabled
-
-        transformer = AllowableCallDirectionTransformer(config)
-
-        mapper.map('direction', AsteriskSCF.Configuration.SipSessionManager.V1.SipAllowableCallDirectionItem(), 'callDirection', 'callDirection', transformer.get, None)
-
-        mapper.map('securetransport', AsteriskSCF.Configuration.SipSessionManager.V1.SipEndpointTransportItem(), 'secureTransport', 'transport', transformer.get, None)
-
-        item = AsteriskSCF.Configuration.SipSessionManager.V1.SipRTPMediaServiceItem()
-        mapper.map('rtpoveripv6', item, 'requireIPv6', 'mediaservice', config.getboolean, None)
-
-        item = AsteriskSCF.Configuration.SipSessionManager.V1.DirectMediaItem()
-        mapper.map('directmedia', item, 'enabled', 'directmedia', config.getboolean, None)
-
-        item = AsteriskSCF.Configuration.SipSessionManager.V1.SipUDPTLMediaServiceItem()
-        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)
-
-        item = AsteriskSCF.Configuration.SipSessionManager.V1.SipCryptoCertificateItem()
-        mapper.map('certificateauthorityfile', item, 'certificateAuthority', 'cryptocert', config.get, None)
-        mapper.map('certificatefile', item, 'certificate', 'cryptocert', config.get, None)
-        mapper.map('privatekeyfile', item, 'privateKey', 'cryptocert', config.get, None)
-        mapper.map('privatekeypassword', item, 'privateKeyPassword', 'cryptocert', config.get, None)
-
-        item = AsteriskSCF.Configuration.SipSessionManager.V1.SipCryptoRequirementsItem()
-        mapper.map('requireverifiedserver', item, 'requireVerifiedServer', 'cryptorequirements', config.getboolean, None)
-        mapper.map('requireverifiedclient', item, 'requireVerifiedClient', 'cryptorequirements', config.getboolean, None)
-        mapper.map('requireclientcertificate', item, 'requireClientCertificate', 'cryptorequirements', config.getboolean, None)
-
-        item = AsteriskSCF.Configuration.SipSessionManager.V1.SipCryptoItem()
-        mapper.map('supportedciphers', item, 'supportedCiphers', 'crypto', config.get, None)
-        mapper.map('tlsservername', item, 'serverName', 'crypto', config.get, None)
-        mapper.map('tlstimeout', item, 'timeout', 'crypto', config.getint, None)
-
-        class TLSProtocolMethodTransformer():
-            def __init__(self, config):
-                self.config = config
-            def get(self, section, item):
-                if self.config.get(section, item) == 'unspecified':
-                    return AsteriskSCF.Configuration.SipSessionManager.V1.TLSProtocolMethod.PROTOCOLMETHODUNSPECIFIED
-                elif self.config.get(section, item) == 'tlsv1':
-                    return AsteriskSCF.Configuration.SipSessionManager.V1.TLSProtocolMethod.PROTOCOLMETHODTLSV1
-                elif self.config.get(section, item) == 'sslv2':
-                    return AsteriskSCF.Configuration.SipSessionManager.V1.TLSProtocolMethod.PROTOCOLMETHODTSSLV2
-                elif self.config.get(section, item) == 'sslv3':
-                    return AsteriskSCF.Configuration.SipSessionManager.V1.TLSProtocolMethod.PROTOCOLMETHODSSLV3
-                elif self.config.get(section, item) == 'sslv23':
-                    return AsteriskSCF.Configuration.SipSessionManager.V1.TLSProtocolMethod.PROTOCOLMETHODSSLV23
-
-        transformer = TLSProtocolMethodTransformer(config)
-        mapper.map('tlsprotocolmethod', item, 'protocolMethod', 'crypto', transformer.get, None)
-
-        class DTMFMethodTransformer():
-            def __init__(self, config):
-                self.config = config
             def get(self, section, item):
-                if self.config.get(section, item) == 'info':
-                    return AsteriskSCF.Configuration.SipSessionManager.V1.SipDTMFOption.INFO
-                if self.config.get(section, item) == 'rfc4733' or self.config.get(section.item) == 'rfc2833':
-                    return AsteriskSCF.Configuration.SipSessionManager.V1.SipDTMFOption.RFC4733
-                if self.config.get(section, item) == 'inband':
-                    return AsteriskSCF.Configuration.SipSessionManager.V1.SipDTMFOption.Inband
-
-        item = AsteriskSCF.Configuration.SipSessionManager.V1.SipDTMFItem()
-        dtmfTransformer = DTMFMethodTransformer(config)
-        mapper.map('dtmfmethod', item, 'dtmf', 'dtmfmethod', dtmfTransformer.get, AsteriskSCF.Configuration.SipSessionManager.V1.SipDTMFOption.RFC4733)
+                if (self.config.get(section, item) == 'playback'):
+                    return AsteriskSCF.Media.File.V1.FileOperations.Playback
+                if (self.config.get(section, item) == 'recording'):
+                    return AsteriskSCF.Media.File.V1.FileOperations.Recording
+                if (self.config.get(section, item) == 'both'):
+                    return AsteriskSCF.Media.File.V1.FileOperations.Both
 
+        mapper = Configurator.OptionMapper()
+        item = AsteriskSCF.Configuration.FileSessionGateway.V1.EndpointDestinationName()
+        mapper.map('destination', item, 'destination', 'destination', config.get, None)
+        item = AsteriskSCF.Configuration.FileSessionGateway.V1.MediaFile()
+        mapper.map('media_id', item, 'id', 'mediaFile', config.get, None)
+        fileOpTransformer = FileOperationTransformer(config)
+        mapper.map('supported_operations', item, 'operations', 'mediaFile', fileOpTransformer.get,
+                   AsteriskSCF.Media.File.V1.FileOperations.Playback)
         for option in config.options(section):
             mapper.execute(group, section, option)
         mapper.finish(group)
-
-        try:
-            formats = config.get(section, 'formats')
-            configuredFormats = formats.split(',')
-            for format in configuredFormats:
-                item = AsteriskSCF.Configuration.SipSessionManager.V1.SipMediaFormatItem()
-
-                front, found, rest = format.partition('/')
-                if found:
-                    item.name = front
-                else:
-                    rest = front
-
-                front, found, rest = rest.partition('@')
-                if found:
-                    if item.name:
-                        item.sampleRate = front
-                    else:
-                        item.name = front
-                else:
-                    rest = front
-
-                front, found, rest = rest.partition(';')
-                if found:
-                    if item.name:
-                        item.frameSize = front
-                    else:
-                        item.name = front
-                else:
-                    rest = front
-
-                item.formatSpecific = [ ]
-
-                if not item.name:
-                    item.name = format
-
-                if item.name:
-                    while rest:
-                        front, found, rest = rest.partition('&')
-                        item.formatSpecific.append(front)
-
-                    group.configurationItems[format] = item
-        except:
-            print 'No configured formats for endpoint ' + section
-
-        try:
-            registrations = config.get(section, 'registrations')
-            registrationList = registrations.split(',')
-            for reg in registrationList:
-                item = AsteriskSCF.Configuration.SipSessionManager.V1.SipRegistrationGroupRef()
-                item.registrationGroupName = reg
-                group.configurationItems[reg] = item
-        except:
-            pass
-
         self.groups.append(group)
 
-    def visit_unsupported(self, config, section):
-        if config.get(section, 'type') == 'transport-udp':
-            self.visit_transport_udp(config, section)
-        elif config.get(section, 'type') == 'transport-tcp':
-            self.visit_transport_tcp(config, section)
-        elif config.get(section, 'type') == 'transport-tls':
-            self.visit_transport_tls(config, section)
-        elif config.get(section, 'type') == 'endpoint':
-            self.visit_endpoint(config, section)
-        elif config.get(section, 'type') == 'registration':
-            self.visit_registration(config, section)
-        elif config.get(section, 'type') == 'identity':
-            self.visit_identity(config, section)
-
... 1569 lines suppressed ...


-- 
asterisk-scf/integration/file_session_gateway.git



More information about the asterisk-scf-commits mailing list