[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
Wed Nov 30 09:34:59 CST 2011


branch "initial_development" has been updated
       via  8e0d0f4e904a813389480705f724858b7eac505b (commit)
       via  09f8ea4796b816882fd51edeb022e915d5ce337f (commit)
      from  377beed4fec4f9bc266ac7932142d275703dae03 (commit)

Summary of changes:
 CMakeLists.txt                                     |    7 +-
 config/FileSessionGatewayConfigurator.py           |  382 +++++++++++++++
 config/FileSessionGatewayTest.conf                 |    6 +
 .../FileSessionReplicationIf.ice                   |  166 ++++---
 slice/CMakeLists.txt                               |   18 +
 src/CMakeLists.txt                                 |   13 +-
 src/Component.cpp                                  |  188 +++++++-
 src/{ReplicationContext.h => ComponentDefs.h}      |   33 +-
 src/ComponentFeature.h                             |    8 +-
 src/Configuration.cpp                              |   62 +++-
 src/CookieManager.cpp                              |  142 ++++++
 src/CookieManager.h                                |  143 ++++++
 src/Endpoint.cpp                                   |  203 +++++++--
 src/Endpoint.h                                     |   31 ++-
 src/EndpointLocator.cpp                            |  188 ++++----
 src/EndpointLocator.h                              |   58 ++-
 src/{Config.h => EndpointSpecification.h}          |   67 ++--
 src/FileSessionGatewayComponent.h                  |    4 +
 src/ReplicatedObject.cpp                           |  127 +++++
 src/ReplicatedObject.h                             |   56 +++
 src/{ReplicationContext.h => ReplicationAdapter.h} |   33 +-
 src/ReplicationListener.cpp                        |  136 ++++++
 src/ReplicationListener.h                          |   15 +-
 src/Replicator.h                                   |   26 +-
 src/ReplicatorListener.h                           |   40 --
 src/Session.cpp                                    |  496 +++++++++++++++-----
 src/Session.h                                      |   92 ++++-
 test/CMakeLists.txt                                |   33 ++
 test/TestCookiesIf.ice                             |   51 ++
 test/TestSessionObject.cpp                         |  459 ++++++++++++++++++
 30 files changed, 2808 insertions(+), 475 deletions(-)
 create mode 100755 config/FileSessionGatewayConfigurator.py
 create mode 100644 config/FileSessionGatewayTest.conf
 create mode 100644 slice/CMakeLists.txt
 copy src/{ReplicationContext.h => ComponentDefs.h} (65%)
 create mode 100644 src/CookieManager.cpp
 create mode 100644 src/CookieManager.h
 copy src/{Config.h => EndpointSpecification.h} (67%)
 create mode 100644 src/ReplicatedObject.cpp
 create mode 100644 src/ReplicatedObject.h
 copy src/{ReplicationContext.h => ReplicationAdapter.h} (56%)
 create mode 100644 src/ReplicationListener.cpp
 delete mode 100644 src/ReplicatorListener.h
 create mode 100644 test/CMakeLists.txt
 create mode 100644 test/TestCookiesIf.ice
 create mode 100644 test/TestSessionObject.cpp


- Log -----------------------------------------------------------------
commit 8e0d0f4e904a813389480705f724858b7eac505b
Author: Brent Eagles <beagles at digium.com>
Date:   Tue Nov 29 16:15:44 2011 -0330

    Fixups for replication and corresponding tests.

diff --git a/config/FileSessionGatewayTest.conf b/config/FileSessionGatewayTest.conf
new file mode 100644
index 0000000..a193178
--- /dev/null
+++ b/config/FileSessionGatewayTest.conf
@@ -0,0 +1,6 @@
+#
+# Configuration file for the FileSessionGatewaySessionTest test driver.
+#
+
+LocatorService.Proxy=LocatorService:tcp -p 4411
+LocatorServiceManagement.Proxy=LocatorServiceManagement:tcp -p 4422
diff --git a/slice/AsteriskSCF/Replication/FileSessionGateway/FileSessionReplicationIf.ice b/slice/AsteriskSCF/Replication/FileSessionGateway/FileSessionReplicationIf.ice
index 2ab5b9a..8d7e781 100644
--- a/slice/AsteriskSCF/Replication/FileSessionGateway/FileSessionReplicationIf.ice
+++ b/slice/AsteriskSCF/Replication/FileSessionGateway/FileSessionReplicationIf.ice
@@ -114,7 +114,7 @@ class MediaSessionState extends SessionState
 
 class SessionListenerUpdate extends SessionState
 {
-    AsteriskSCF::SessionCommunications::V1::SessionListener* listener;
+    AsteriskSCF::SessionCommunications::V1::SessionListenerSeq listeners;
 };
 
 class BridgeState extends SessionState
diff --git a/src/ReplicatedObject.cpp b/src/ReplicatedObject.cpp
new file mode 100644
index 0000000..fd0ed0e
--- /dev/null
+++ b/src/ReplicatedObject.cpp
@@ -0,0 +1,127 @@
+/*
+ * 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 "ReplicatedObject.h"
+#include <string>
+
+using namespace AsteriskSCF::FileSessionGtw;
+using namespace std;
+
+ReplicatedObject::ReplicatedObject(const std::string& key) :
+    mKey(key)
+{
+    //
+    // Nothing to do here.
+    //
+}
+
+ReplicatedObject::ReplicatedObject(const std::string& key, const ReplicatorSmartProxy& replicator) :
+    mKey(key),
+    mReplicator(replicator)
+{
+}
+
+void ReplicatedObject::updateReplicator(const ReplicatorSmartProxy& replicator)
+{
+    //
+    // Assignment of instances of SmartProxy are supposed to be thread safe.
+    //
+    mReplicator = replicator;
+    onProxyUpdate();
+}
+
+void ReplicatedObject::update(const AsteriskSCF::Replication::FileSessionGateway::V1::StateItemPtr& stateUpdate)
+{
+    AsteriskSCF::Replication::FileSessionGateway::V1::StateItemSeq seq;
+    seq.push_back(stateUpdate);
+    update(seq);
+}
+
+void ReplicatedObject::update(const AsteriskSCF::Replication::FileSessionGateway::V1::StateItemSeq& updates)
+{
+    if (mReplicator)
+    {
+        try
+        {
+            mReplicator->setState(updates);
+        }
+        catch (const AsteriskSCF::Core::Discovery::V1::ServiceNotFound&)
+        {
+            //
+            // Really should not happen.
+            //
+        }
+    }
+}
+
+void ReplicatedObject::remove(const Ice::StringSeq& items)
+{
+    if (mReplicator)
+    {
+        try
+        {
+            mReplicator->removeState(items);
+        }
+        catch (const AsteriskSCF::Core::Discovery::V1::ServiceNotFound&)
+        {
+            //
+            // Really should not happen.
+            //
+        }
+    }
+}
+
+void ReplicatedObject::remove(const string& key)
+{
+    Ice::StringSeq items;
+    items.push_back(key);
+    remove(items);
+}
+
+void ReplicatedObject::remove(const AsteriskSCF::Replication::FileSessionGateway::V1::StateItemSeq& itemsToRemove)
+{
+    if (mReplicator)
+    {
+        try
+        {
+            mReplicator->removeStateForItems(itemsToRemove);
+        }
+        catch (const AsteriskSCF::Core::Discovery::V1::ServiceNotFound&)
+        {
+            //
+            // Really should not happen.
+            //
+        }
+    }
+}
+
+std::string ReplicatedObject::getKey()
+{
+    //
+    // mKey is immutable and does not require a lock.
+    //
+    return mKey;
+}
+ 
+void ReplicatedObject::onProxyUpdate()
+{
+    //
+    // Default implementation does nothing. Derived objects may want to push the new proxy to children,
+    // log change, etc.
+    //
+}
+
+
diff --git a/src/ReplicatedObject.h b/src/ReplicatedObject.h
index 15942b4..0b164c9 100644
--- a/src/ReplicatedObject.h
+++ b/src/ReplicatedObject.h
@@ -33,8 +33,8 @@ namespace FileSessionGtw
 class ReplicatedObject
 {
 public:
-    ReplicatedObject();
-    ReplicatedObject(const ReplicatorSmartProxy& replicator);
+    ReplicatedObject(const std::string& id);
+    ReplicatedObject(const std::string& id, const ReplicatorSmartProxy& replicator);
     virtual ~ReplicatedObject() {}
     void updateReplicator(const ReplicatorSmartProxy& replicator);
     void update(const AsteriskSCF::Replication::FileSessionGateway::V1::StateItemPtr& stateUpdate);
@@ -42,8 +42,11 @@ public:
     void remove(const Ice::StringSeq& items);
     void remove(const std::string& item);
     void remove(const AsteriskSCF::Replication::FileSessionGateway::V1::StateItemSeq& itemsToRemove);
+
+    std::string getKey();
     
 protected:
+    std::string mKey;
     ReplicatorSmartProxy mReplicator;
 
     virtual void onProxyUpdate();
diff --git a/src/Session.cpp b/src/Session.cpp
index 04d8fbe..b579062 100644
--- a/src/Session.cpp
+++ b/src/Session.cpp
@@ -75,6 +75,7 @@ public:
         const string& endpointKey,
         const Ice::ObjectAdapterPtr& adapter, 
         const Logger& logger) :
+        SessionImpl(id),
         mServiceLocator(locator),
         mAdapter(adapter),
         mPublicProxy(myPublicProxy),
@@ -112,6 +113,7 @@ public:
                     stateUpdate =
                         createUpdate<AsteriskSCF::Replication::FileSessionGateway::V1::SessionListenerUpdatePtr>(
                             mId + ".listener." + idString);
+                    copyListeners(stateUpdate->listeners);
                 }
             }
             if (stateUpdate)
@@ -292,7 +294,7 @@ public:
     {
         try
         {
-            string removalKey;
+            Replication::BridgeStatePtr stateUpdate;
             {
                 UniqueLock lock(mLock);
                 stateCheckNoLock();
@@ -301,18 +303,22 @@ public:
                     throw NotBridged();
                 }
                 Ice::CommunicatorPtr c = mAdapter->getCommunicator();
-                removalKey = mId + ".bridge";
+                stateUpdate = createUpdate<Replication::BridgeStatePtr>(mId + ".bridge");
                 mBridge = BridgePrx();
                 string idString = c->identityToString(listener->ice_getIdentity());
                 Listeners::iterator iter = mListeners.find(idString);
                 if (iter != mListeners.end())
                 {
                     mListeners.erase(iter);
+                    stateUpdate->listener = listener;
                 }
             }
-            if (!removalKey.empty())
+            //
+            // removing a bridge is not replicated by "removal", but a change in state values.
+            //
+            if (stateUpdate)
             {
-                remove(removalKey);
+                update(stateUpdate);
             }
             cb->ice_response();
         }
@@ -410,25 +416,34 @@ public:
         cb->ice_response(AsteriskSCF::SessionCommunications::PartyIdentification::V1::ConnectedLinePtr());
     }
     
+    bool isDestroyed()
+    {
+        SharedLock lock(mLock);
+        return mDestroyed;
+    }
+
     void destroy()
     {
         UniqueLock lock(mLock);
         mDestroyed = true;
     }
 
-    ReplicationAdapterPtr getReplicationAdapter();
-
-    bool isDestroyed()
+    string getId()
     {
         SharedLock lock(mLock);
-        return mDestroyed;
+        return mId;
     }
 
-    string getId()
+    ReplicationAdapterPtr getReplicationAdapter();
+
+    AsteriskSCF::SessionCommunications::V1::SessionListenerSeq getSessionListeners()
     {
+        AsteriskSCF::SessionCommunications::V1::SessionListenerSeq result;
         SharedLock lock(mLock);
-        return mId;
+        copyListeners(result);
+        return result;
     }
+        
 
     void cookiesSet(const SessionCookies&)
     {
@@ -486,23 +501,24 @@ public:
         mCookieManager->resetCookies(cookie->cookies);
     }
 
-    void addListener(const Replication::SessionListenerUpdatePtr& listener)
+    void setListeners(const Replication::SessionListenerUpdatePtr& listenerUpdate)
     {
-        string idString = mAdapter->getCommunicator()->identityToString(listener->listener->ice_getIdentity());
         UniqueLock lock(mLock);
-        mListeners[idString] = listener->listener;
-        mLogger(Trace) << "(Replication: " << mId << "): adding listener " << idString;
+        mListeners.clear();
+        for (AsteriskSCF::SessionCommunications::V1::SessionListenerSeq::const_iterator iter =
+                 listenerUpdate->listeners.begin(); iter != listenerUpdate->listeners.end(); ++iter)
+        {
+            if (!(*iter))
+            {
+                continue;
+            }
+            string idString = mAdapter->getCommunicator()->identityToString((*iter)->ice_getIdentity());
+            mListeners[idString] = (*iter);
+        }
     }
 
-    void removeListener(const Replication::SessionListenerUpdatePtr& listener)
+    void setMediaSessionId(const Replication::MediaSessionIdStatePtr&)
     {
-        string idString = mAdapter->getCommunicator()->identityToString(listener->listener->ice_getIdentity());
-        UniqueLock lock(mLock);
-        Listeners::iterator iter = mListeners.find(idString);
-        if (iter != mListeners.end())
-        {
-            mLogger(Trace) << "(Replication:" << mId << "): removing listener " << idString;
-        }
     }
 
     void setMediaSession(const Replication::MediaSessionStatePtr&)
@@ -522,8 +538,21 @@ public:
     {
     }
 
-    void setSessionControllerId(const Replication::SessionControllerIdState&)
+    void setSessionControllerId(const Replication::SessionControllerIdStatePtr&)
+    {
+    }
+
+    //
+    // This *could* be private, but it's been made public to facilitate testing.
+    //
+    template <typename T>
+    T createUpdate(const string& itemKey)
     {
+        T result = new typename T::element_type;
+        result->key = itemKey;
+        result->endpointItemKey = mEndpointKey;
+        result->sessionId = mId;
+        return result;
     }
 
 private:
@@ -578,46 +607,78 @@ private:
         return info;
     }
 
-    template <typename T>
-    T createUpdate(const string& itemKey)
+    void copyListeners(AsteriskSCF::SessionCommunications::V1::SessionListenerSeq& seq)
     {
-        T result = new typename T::element_type;
-        result->key = itemKey;
-        result->endpointItemKey = mEndpointKey;
-        result->sessionId = mId;
-        return result;
+        seq.clear();
+        for (Listeners::const_iterator iter = mListeners.begin(); iter != mListeners.end(); ++iter)
+        {
+            seq.push_back(iter->second);
+        }
     }
 };
 
 typedef IceUtil::Handle<SessionServant> SessionServantPtr;
 
+#define CHECK_AND_DISPATCH_UPDATE(T, Object, Method, Update)   \
+    {                                                          \
+        T v = T::dynamicCast(Update);                          \
+        if (v)                                                 \
+        {                                                      \
+            Object->Method(v);                                 \
+            return;                                            \
+        }                                                      \
+    }
+    
+
 class SessionReplicationAdapter : public ReplicationAdapter
 {
 public:
 
-    SessionReplicationAdapter(const SessionServantPtr& sessionServant) :
-        mSession(sessionServant)
+    SessionReplicationAdapter(const SessionServantPtr& sessionServant,
+        const Logger& logger) :
+        mSession(sessionServant),
+        mLogger(logger)
     {
+        assert(mSession);
     }
     
-    void update(const AsteriskSCF::Replication::FileSessionGateway::V1::StateItemPtr&)
-    {
-        //
-        // XXX:
-        //
+    void update(const AsteriskSCF::Replication::FileSessionGateway::V1::StateItemPtr& update)
+    {
+        CHECK_AND_DISPATCH_UPDATE(Replication::MediaSessionStatePtr, mSession, setMediaSession, update);
+        CHECK_AND_DISPATCH_UPDATE(Replication::SessionControllerIdStatePtr, mSession, setSessionControllerId, update);
+        CHECK_AND_DISPATCH_UPDATE(Replication::SourcesStatePtr, mSession, setSourcesState, update);
+        CHECK_AND_DISPATCH_UPDATE(Replication::SinksStatePtr, mSession, setSinks, update);
+        CHECK_AND_DISPATCH_UPDATE(Replication::StreamsStatePtr, mSession, setStreams, update);
+        CHECK_AND_DISPATCH_UPDATE(Replication::MediaSessionIdStatePtr, mSession, setMediaSessionId, update);
+        CHECK_AND_DISPATCH_UPDATE(Replication::SessionListenerUpdatePtr, mSession, setListeners, update);
+        CHECK_AND_DISPATCH_UPDATE(Replication::BridgeStatePtr, mSession, setBridge, update);
+        CHECK_AND_DISPATCH_UPDATE(Replication::CookieStatePtr, mSession, setCookies, update);
+        Replication::SessionStatePtr sessionUpdate = Replication::SessionStatePtr::dynamicCast(update);
+        if (!sessionUpdate)
+        {
+            mLogger(Error) << "A non-session replication update was routed to a session object";
+            return;
+        }
     }
 
     void destroy()
     {
+        mSession->destroy();
     }
 
 private:
     SessionServantPtr mSession;
+    Logger mLogger;
 };
 
 ReplicationAdapterPtr SessionServant::getReplicationAdapter()
 {
-    return ReplicationAdapterPtr(new SessionReplicationAdapter(this));
+    return ReplicationAdapterPtr(new SessionReplicationAdapter(this, mLogger));
+}
+
+SessionImpl::SessionImpl(const string& id) :
+    ReplicatedObject(id)
+{
 }
 
 SessionImplPtr SessionImpl::create(
diff --git a/src/Session.h b/src/Session.h
index 57393bf..32f88a6 100644
--- a/src/Session.h
+++ b/src/Session.h
@@ -32,24 +32,75 @@ namespace AsteriskSCF
 namespace FileSessionGtw
 {
 
+/**
+ *
+ * Base class for the FileSessionGateway's session implementation. This
+ * class defines methods that are used by the other objects in the
+ * FileSessionGateway.
+ *
+ */
 class SessionImpl : public AsteriskSCF::SessionCommunications::V1::Session, public ReplicatedObject
 {
 public:
 
-    virtual bool isDestroyed() = 0;
+    SessionImpl(const std::string& id);
 
-    virtual std::string getId() = 0;
+    /**
+     *
+     * Check to see if the object has been marked as "destroyed". A
+     * destroyed object is pending deletion but some state is still
+     * available for further internal processing.
+     *
+     * @returns true if the object has been destroyed.
+     *
+     */
+    virtual bool isDestroyed() = 0;
 
+    /**
+     *
+     * Mark this object as destroyed.
+     *
+     */
     virtual void destroy() = 0;
 
+    /**
+     *
+     * Get the internal id. This id must be relatively unique (can be
+     * repeated in a component's lifetime, but two objects of the same type
+     * may not share the same id at the same time).
+     *
+     * @returns a string containing the current id.
+     *
+     */
+    virtual std::string getId() = 0;
+
+    /**
+     *
+     * Get the replication adapter for this object. To be used by
+     * replication responders to update this object. 
+     *
+     * @returns a replication adapter instance for this session instance. Note: this may be a new instance
+     * each time it is called so pointer comparisons to determine if an adapter "belongs" to a particular
+     * object is not supported.
+     *
+     */
     virtual ReplicationAdapterPtr getReplicationAdapter() = 0;
 
     /**
      *
-     * @param adapter The Ice object adapter that objects instantiated by the
-     *   calls on the Session object should be activated on.
-     *  
-     * @param myProxy The proxy that can be used to access to this object. 
+     * Get the session listeners that are currently registered with this session.
+     *
+     * @returns a sequence of session listener proxies.
+     *
+     */
+    virtual AsteriskSCF::SessionCommunications::V1::SessionListenerSeq getSessionListeners() = 0;
+
+    /**
+     *
+     * Create a new instance of a session object.
+     *
+     * TODO: document parameters.
+     *
      */
     static IceUtil::Handle<SessionImpl> create(
         const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& locator,
@@ -60,6 +111,13 @@ public:
         const Ice::ObjectAdapterPtr& adapter,
         const AsteriskSCF::System::Logging::Logger& logger);
 
+    /**
+     *
+     * Create a replica of a session object.
+     *
+     * TODO: document parameters.
+     *
+     */
     static IceUtil::Handle<SessionImpl> create(
         const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& locator,
         const AsteriskSCF::Replication::FileSessionGateway::V1::SessionDefinitionStatePtr& sessionState,
diff --git a/test/TestSessionObject.cpp b/test/TestSessionObject.cpp
index 6a1784b..44ed6f5 100644
--- a/test/TestSessionObject.cpp
+++ b/test/TestSessionObject.cpp
@@ -39,9 +39,57 @@ using namespace std;
 using namespace boost::unit_test;
 using namespace AsteriskSCF::FileSessionGtw;
 
+//namespace Replication = AsteriskSCF::Replication::FileSessionGateway::V1;
+
+struct IndicationRecord
+{
+    AsteriskSCF::SessionCommunications::V1::SessionPrx source;
+    AsteriskSCF::SessionCommunications::V1::IndicationPtr indication;
+    AsteriskSCF::SessionCommunications::V1::SessionCookies cookies;
+};
+typedef vector<IndicationRecord> Indications;
+
+class TestSessionListener : public AsteriskSCF::SessionCommunications::V1::SessionListener
+{
+public:
+    TestSessionListener()
+    {
+    }
+    
+    void indicated(const AsteriskSCF::SessionCommunications::V1::SessionPrx& source,
+        const AsteriskSCF::SessionCommunications::V1::IndicationPtr& indication,
+        const AsteriskSCF::SessionCommunications::V1::SessionCookies& cookies,
+        const Ice::Current&)
+    {
+        UniqueLock lock(mLock);
+        IndicationRecord record;
+        record.source = source;
+        record.indication = indication;
+        record.cookies = cookies;
+        mIndicationLog.push_back(record);
+    }
+
+    Indications getLog()
+    {
+        SharedLock lock(mLock);
+        return mIndicationLog;
+    }
+
+    void clearLog()
+    {
+        UniqueLock lock(mLock);
+        mIndicationLog.clear();
+    }
+
+private:
+    boost::shared_mutex mLock;
+    Indications mIndicationLog;
+};
+typedef IceUtil::Handle<TestSessionListener> TestSessionListenerPtr;
+
 /**
  *
- * Simple test to validate the CookieManager helper class.
+ * Simple test suite to validate the CookieManager helper class.
  *
  */
 typedef boost::shared_ptr<AsteriskSCF::SessionCommunications::V1::SessionCookies> SessionCookiesPtr;
@@ -54,6 +102,9 @@ public:
     {
     }
 
+    //
+    // Test listener to verify listener updates. Simply takes a smart pointer to a cookie sequence.
+    //
     class TestListener : public CookieManagerListener
     {
     public:
@@ -86,7 +137,10 @@ public:
         SessionCookiesPtr mCookiesRef;
     };
     typedef boost::shared_ptr<TestListener> TestListenerPtr;
-    
+
+    //
+    // These could be broken into separate tests.
+    //
     void testCookieOps()
     {
         SessionCookiesPtr cookieCapture(new AsteriskSCF::SessionCommunications::V1::SessionCookies);
@@ -214,15 +268,146 @@ public:
         mObjectAdapter(adapter),
         mLogger(logger)
     {
+        cerr << mCommunicator->getProperties()->getProperty("LocatorService.Proxy") << endl;
+        mLocator = AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx::uncheckedCast(
+            mCommunicator->propertyToProxy("LocatorService.Proxy"));
+        //
+        // Note: BOOST test framework methods cannot be used here yet since the framework
+        // isn't initialized yet.
+        //
+    }
+
+    //
+    // Exercise the methods declared in Session.h.
+    //
+    void implementationInterfaceTests()
+    {
+        //
+        // Exercise the implementation interfaces defined in Session.h
+        //
+        SessionImplPtr session = createTestSessionObject();
+        BOOST_REQUIRE(!session->isDestroyed());
+        BOOST_REQUIRE(session->getId() == "TestSession");
+        AsteriskSCF::FileSessionGtw::ReplicationAdapterPtr replicationAdapter =
+            session->getReplicationAdapter();
+        BOOST_REQUIRE(replicationAdapter);
+        session->destroy();
+        BOOST_REQUIRE(session->isDestroyed());
+
+        //
+        // Note: the replication adapter itself is tested elsewhere.
+        //
+
+        //
+        // Reminder: if the test is modified to register anything with the
+        // Ice runtime, it should be removed now.
+        //
+    }
+
+    //
+    // Exercise the session's replication adapter.
+    //
+    void testReplicationAdapter()
+    {
+        BOOST_REQUIRE(mLocator);
+        SessionServantPtr session = createTestSessionObject();
+        AsteriskSCF::FileSessionGtw::ReplicationAdapterPtr replicationAdapter =
+            session->getReplicationAdapter();
+        BOOST_REQUIRE(replicationAdapter);
+        
+        //
+        // How this test works is we create examples of state replications
+        // and feed them to the replication adapter. We can then example
+        // the state of session to determine the success or failure fo the
+        // replication.
+        //
+        AsteriskSCF::SessionCommunications::V1::BridgePrx bridgePrx =
+            AsteriskSCF::SessionCommunications::V1::BridgePrx::uncheckedCast(
+                mObjectAdapter->createProxy(mCommunicator->stringToIdentity("TestBridge")));
+        TestSessionListenerPtr listener = new TestSessionListener;
+        Ice::Identity listenerId = mCommunicator->stringToIdentity("TestSessionListener");
+        AsteriskSCF::SessionCommunications::V1::SessionListenerPrx listenerPrx =
+            AsteriskSCF::SessionCommunications::V1::SessionListenerPrx::uncheckedCast(mObjectAdapter->add(listener, listenerId));
+
+        Ice::ObjectPrx objPrx = mObjectAdapter->add(session, mCommunicator->stringToIdentity("TestSession"));
+
+        //
+        // Since the session objects implement some methods as AMD, we need
+        // to create a non collocation optimized proxy.
+        //
+        AsteriskSCF::SessionCommunications::V1::SessionPrx sessionPrx =
+            AsteriskSCF::SessionCommunications::V1::SessionPrx::uncheckedCast(objPrx->ice_collocationOptimized(false));
+                    
+        try
+        {
+            Replication::BridgeStatePtr bridgeUpdate =
+                session->createUpdate<Replication::BridgeStatePtr>(session->getId() + ".bridge");
+            bridgeUpdate->bridgeProxy = bridgePrx;
+            bridgeUpdate->listener = listenerPrx;
+
+            replicationAdapter->update(bridgeUpdate);
+
+            AsteriskSCF::SessionCommunications::V1::BridgePrx returnedBridge = sessionPrx->getBridge();
+            BOOST_CHECK(returnedBridge->ice_getIdentity() == bridgePrx->ice_getIdentity());
+
+            AsteriskSCF::SessionCommunications::V1::SessionListenerSeq listeners = session->getSessionListeners();
+            BOOST_CHECK(listeners.size() == 1);
+            BOOST_CHECK(listeners[0]->ice_getIdentity() == listenerId);
+
+            bridgeUpdate->bridgeProxy = AsteriskSCF::SessionCommunications::V1::BridgePrx();
+            replicationAdapter->update(bridgeUpdate);
+            returnedBridge = sessionPrx->getBridge();
+            BOOST_CHECK(!returnedBridge);
+            listeners = session->getSessionListeners();
+            BOOST_CHECK(listeners.empty());
+        }
+        catch (const std::exception& ex)
+        {
+            mLogger(Error) << __FILE__ << ':' << __LINE__ << " - " << "Unexpected " << ex.what();
+            BOOST_REQUIRE(false);
+        }
+        catch (...)
+        {
+            mLogger(Error) << __FILE__ << ':' << __LINE__ << " - " << "Unexpected unknown exception.";
+            BOOST_REQUIRE(false);
+        }
+        try
+        {
+            mObjectAdapter->remove(listenerId);
+        }
+        catch (...)
+        {
+            BOOST_REQUIRE(false);
+        }
     }
 
-    void fooTest()
+    //
+    // Helper function for creating a test session object.
+    //
+    SessionServantPtr createTestSessionObject()
     {
-        BOOST_REQUIRE(true);
+        BOOST_REQUIRE(mLocator);
+        AsteriskSCF::SessionCommunications::V1::SessionPrx testProxy =
+            AsteriskSCF::SessionCommunications::V1::SessionPrx::uncheckedCast(
+                mObjectAdapter->createProxy(mCommunicator->stringToIdentity("TestSession")));
+        AsteriskSCF::SessionCommunications::V1::SessionEndpointPrx testEndpoint =
+            AsteriskSCF::SessionCommunications::V1::SessionEndpointPrx::uncheckedCast(
+                mObjectAdapter->createProxy(mCommunicator->stringToIdentity("TestEndpoint")));
+        
+        //
+        // Exercise the implementation interfaces defined in Session.h
+        //
+        SessionServantPtr session = SessionServantPtr::dynamicCast(
+            SessionImpl::create(mLocator, testProxy, testEndpoint, "TestSession", "TestEndpoint", mObjectAdapter,
+                mLogger));
+        BOOST_REQUIRE(session);
+        return session;
     }
+    
 private:
     Ice::CommunicatorPtr mCommunicator;
     Ice::ObjectAdapterPtr mObjectAdapter;
+    AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx mLocator;
     Logger mLogger;
 };
 
@@ -232,7 +417,10 @@ boost::shared_ptr<CookieManagerTests> cookieManagerSuite;
 bool init_unit_test()
 {
     framework::master_test_suite().add(BOOST_TEST_CASE(
-            boost::bind(&SessionObjectTests::fooTest, sessionObjectSuite)));
+            boost::bind(&SessionObjectTests::implementationInterfaceTests, sessionObjectSuite)));
+    framework::master_test_suite().add(BOOST_TEST_CASE(
+            boost::bind(&SessionObjectTests::testReplicationAdapter, sessionObjectSuite)));
+
 
     framework::master_test_suite().add(BOOST_TEST_CASE(
             boost::bind(&CookieManagerTests::testCookieOps, cookieManagerSuite)));
@@ -249,6 +437,7 @@ int main(int argc, char** argv)
         Ice::ObjectAdapterPtr objectAdapter = communicator->createObjectAdapterWithEndpoints(
             "UnitTestAdapter", communicator->getProperties()->getPropertyWithDefault(
                 "UnitTestAdapter.Endpoints", "default"));
+        objectAdapter->activate();
         //
         // Initialize test suite objects.
         //

commit 09f8ea4796b816882fd51edeb022e915d5ce337f
Author: Brent Eagles <beagles at digium.com>
Date:   Mon Nov 28 06:32:06 2011 -0330

    Lots of additions, reworkings, refactoring and some test code.

diff --git a/CMakeLists.txt b/CMakeLists.txt
index c049ee8..dd29684 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,8 +1,11 @@
 astscf_project(FileSessionGateway 3.4)
 
-add_subdirectory(src)
+add_subdirectory(slice)
+# add_subdirectory(src)
+add_subdirectory(test)
+
 #
-#if(BUILD_TESTING)
+#(BUILD_TESTING)
 #
 #  add_subdirectory(test)
 #endif()
diff --git a/config/FileSessionGatewayConfigurator.py b/config/FileSessionGatewayConfigurator.py
new file mode 100755
index 0000000..3da565e
--- /dev/null
+++ b/config/FileSessionGatewayConfigurator.py
@@ -0,0 +1,382 @@
+#!/usr/bin/env python
+
+#
+# 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.
+#
+
+# FileSessionGateway configurator
+
+# Bring in the common configuration infrastructure
+import ConfigParser, Ice, Configurator, sys, os, traceback
+
+# Load our component specific configuration definitions
+Ice.loadSlice("--underscore -I\"" + os.environ["ASTSCF_HOME"] + "\"" + " -I" + Ice.getSliceDir() + " --all ../slice/AsteriskSCF/Configuration/FileSessionGateway/FileSessionGatewayConfigurationIf.ice")
+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)
+
+    def visit_transport_udp(self, config, section):
+        group = AsteriskSCF.Configuration.SipSessionManager.V1.SipUDPTransportGroup()
+        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_tcp(self, config, section):
+        group = AsteriskSCF.Configuration.SipSessionManager.V1.SipTCPTransportGroup()
+        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_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:
+            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)
+
+        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)
+
+# In order to do service locator based lookup we need to pass in a params object
+serviceLocatorParams = AsteriskSCF.Core.Discovery.V1.ServiceLocatorParams()
+serviceLocatorParams.category = AsteriskSCF.Configuration.SipSessionManager.V1.ConfigurationDiscoveryCategory
+serviceLocatorParams.service = 'default' 
+
+# Make a configurator application and let it run
+app = Configurator.ConfiguratorApp('Sip.config', SipSectionVisitors(), None, serviceLocatorParams)
+sys.exit(app.main(sys.argv))
diff --git a/slice/AsteriskSCF/Replication/FileSessionGateway/FileSessionReplicationIf.ice b/slice/AsteriskSCF/Replication/FileSessionGateway/FileSessionReplicationIf.ice
index fc9d718..2ab5b9a 100644
--- a/slice/AsteriskSCF/Replication/FileSessionGateway/FileSessionReplicationIf.ice
+++ b/slice/AsteriskSCF/Replication/FileSessionGateway/FileSessionReplicationIf.ice
@@ -36,69 +36,109 @@ module FileSessionGateway
 ["suppress"]
 module V1
 {
-   const string StateReplicatorComponentCategory = "FileSessionReplicatorComponent";
-   const string StateReplicatorDiscoveryCategory = "FileSessionReplicator";
-
-   class StateItem
-   {
-      string key;
-      string sessionId;
-   };
-
-   sequence<StateItem> StateItemSeq;
-
-   interface StateReplicatorListener
-   {
-      void stateRemoved(Ice::StringSeq itemKeys);
-      void stateRemovedForItems(StateItemSeq items);
-      void stateSet(StateItemSeq items);
-   };
-
-   interface StateReplicator
-   {
-      void addListener(StateReplicatorListener *listener);
-      void removeListener(StateReplicatorListener *listener);
-      void setState (StateItemSeq items);
-      void removeState(Ice::StringSeq items);
-      void removeStateForItems(StateItemSeq items);
-      idempotent StateItemSeq getState(Ice::StringSeq iteKeys);
-      idempotent StateItemSeq getAllState();
-   };
-
-   sequence<AsteriskSCF::Media::File::V1::FileSession*> MediaSessionSeq;
-
-   class SessionState extends StateItem
-   {
-      string endpointName;
-
-      Ice::Identity sessionObjectId;
-      Ice::Identity mediaSessionObjectId;
-      Ice::Identity sessionControllerObjectId;
-
-      AsteriskSCF::Media::V1::StreamSourceSeq sources;
-      AsteriskSCF::Media::V1::StreamSinkSeq sinks;
-      AsteriskSCF::Media::V1::StreamInformationDict streams;
-
-      MediaSessionSeq rtpMediaSessions;
-
-      AsteriskSCF::SessionCommunications::V1::SessionListenerSeq listeners;
-
-      AsteriskSCF::SessionCommunications::V1::Bridge *bridge;
-
-      AsteriskSCF::SessionCommunications::V1::SessionCookieDict cookies;
-   };
-
-   class DefaultSessionListenerItem extends StateItem
-   {
-      string endpointName;
-      AsteriskSCF::SessionCommunications::V1::SessionListener* listener;
-   };
-
-   class DefaultSessionCookieItem extends StateItem
-   {
-      string endpointName;
-      AsteriskSCF::SessionCommunications::V1::SessionCookie cookie;
-   };
+
+const string StateReplicatorComponentCategory = "FileSessionReplicatorComponent";
+const string StateReplicatorDiscoveryCategory = "FileSessionReplicator";
+ 
+class StateItem
+{
+    string key;
+};
+
+sequence<StateItem> StateItemSeq;
+
+interface StateReplicatorListener
+{
+    void stateRemoved(Ice::StringSeq itemKeys);
+    void stateRemovedForItems(StateItemSeq items);
+    void stateSet(StateItemSeq items);
+};
+
+interface StateReplicator
+{
+    void addListener(StateReplicatorListener *listener);
+    void removeListener(StateReplicatorListener *listener);
+    void setState (StateItemSeq items);
+    void removeState(Ice::StringSeq items);
+    void removeStateForItems(StateItemSeq items);
+    idempotent StateItemSeq getState(Ice::StringSeq iteKeys);
+    idempotent StateItemSeq getAllState();
+};
+
+sequence<AsteriskSCF::Media::File::V1::FileSession*> MediaSessionSeq;
+
+class SessionDefinitionState extends StateItem
+{
+    string endpointName;
+    string endpointItemKey;
+    string sessionId;
+    Ice::Identity sessionObjectId;
+    AsteriskSCF::SessionCommunications::V1::Session* publishedProxy;
+};
+
+class SessionState extends StateItem
+{
+    string endpointItemKey;
+    string sessionId;
+};
+
+class MediaSessionIdState extends SessionState
+{
+    Ice::Identity mediaSessionObjectId;
+};
+
+class SessionControllerIdState extends SessionState
+{
+    Ice::Identity sessionControllerObjectId;
+};
+
+class SourcesState extends SessionState
+{
+    AsteriskSCF::Media::V1::StreamSourceSeq sources;
+};
+
+class SinksState extends SessionState
+{
+    AsteriskSCF::Media::V1::StreamSinkSeq sinks;
+};
+
+class StreamsState extends SessionState
+{
+    AsteriskSCF::Media::V1::StreamInformationDict streams;
+};
+
+class MediaSessionState extends SessionState
+{
+    MediaSessionSeq rtpMediaSessions;
+};
+
+class SessionListenerUpdate extends SessionState
+{
+    AsteriskSCF::SessionCommunications::V1::SessionListener* listener;
+};
+
+class BridgeState extends SessionState
+{
+    AsteriskSCF::SessionCommunications::V1::Bridge* bridgeProxy;
+    AsteriskSCF::SessionCommunications::V1::SessionListener* listener;
+};
+
+class CookieState extends SessionState
+{
+    AsteriskSCF::SessionCommunications::V1::SessionCookies cookies;
+};
+
+class DefaultSessionListenerItem extends StateItem
+{
+    string endpointName;
+    AsteriskSCF::SessionCommunications::V1::SessionListener* listener;
+};
+
+class DefaultSessionCookieItem extends StateItem
+{
+    string endpointName;
+    AsteriskSCF::SessionCommunications::V1::SessionCookie cookie;
+};
 
 }; /* module V1 */
 
diff --git a/slice/CMakeLists.txt b/slice/CMakeLists.txt
new file mode 100644
index 0000000..90e1e47
--- /dev/null
+++ b/slice/CMakeLists.txt
@@ -0,0 +1,18 @@
+set(LIBNAME "AstScfFileSessionGatewayAPI")
+
+astscf_slice_collection(GLOBAL
+	NAME FILESESSIONGATEWAY
+	PATH "${CMAKE_CURRENT_SOURCE_DIR}"
+	HEADERS
+	"${CMAKE_CURRENT_BINARY_DIR}/${LIBNAME}/slice-FILESESSIONGATEWAY"
+	LIBRARY ${LIBNAME}
+	)
+
+astscf_slice_include_collection(FILESESSIONGATEWAY)
+
+astscf_component_init(${LIBNAME})
+astscf_component_add_slices(${LIBNAME} FILESESSIONGATEWAY GLOB_RECURSE
+    "AsteriskSCF/*.ice")
+astscf_component_add_slice_collection_libraries(${LIBNAME} ASTSCF)
+astscf_component_build_library(${LIBNAME})
+astscf_slice_collection_install(FILESESSIONGATEWAY)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 144f394..0244db1 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -12,8 +12,12 @@ astscf_component_add_files(FileSessionGateway
     EndpointLocator.h
     EndpointLocator.cpp
     LoggerF.h
-    ReplicationContext.h
+    CookieManager.cpp
+    CookieManager.h
+    ReplicatedObject.cpp
+    ReplicatedObject.h
     Replication.h
+    Replicator.h
     ReplicationListener.h
     Session.h
     Session.cpp
@@ -21,15 +25,10 @@ astscf_component_add_files(FileSessionGateway
 astscf_component_add_files(FileSessionGateway Component.cpp)
 astscf_component_add_files(FileSessionGateway Configuration.cpp)
 astscf_component_add_files(FileSessionGateway Configuration.h)
-astscf_component_add_slices(FileSessionGateway PROJECT 
-    AsteriskSCF/FileSessionGateway/FileSessionGatewayIf.ice
-    AsteriskSCF/Configuration/FileSessionGateway/FileSessionGatewayConfigurationIf.ice   
-    AsteriskSCF/Replication/FileSessionGateway/FileSessionReplicationIf.ice
-    )
 
 astscf_component_add_ice_libraries(FileSessionGateway IceStorm)
 astscf_component_add_boost_libraries(FileSessionGateway core)
-astscf_component_add_slice_collection_libraries(FileSessionGateway ASTSCF)
+astscf_component_add_slice_collection_libraries(FileSessionGateway FILESESSIONGATEWAY ASTSCF)
 astscf_component_build_icebox(FileSessionGateway)
 target_link_libraries(FileSessionGateway astscf-ice-util-cpp logging-client)
 astscf_component_install(FileSessionGateway)
diff --git a/src/Component.cpp b/src/Component.cpp
index 5013318..1c10863 100644
--- a/src/Component.cpp
+++ b/src/Component.cpp
@@ -13,7 +13,16 @@
  * the GNU General Public License Version 2. See the LICENSE.txt file
  * at the top of the source tree.
  */
+
+#include "EndpointLocator.h"
+#include "FileSessionGatewayComponent.h"
+#include "Config.h"
+#include "Replicator.h"
+#include "ReplicationListener.h"
+#include "ComponentDefs.h"
+
 #include <AsteriskSCF/Component/Component.h>
+
 #include <IceUtil/UUID.h>
 
 #include <boost/thread.hpp>
@@ -28,18 +37,8 @@
 #include <AsteriskSCF/Logger/IceLogger.h>
 #include <AsteriskSCF/logger.h>
 
-#include "EndpointLocator.h"
-// #include "ReplicationListener.h"
-// #include "ReplicationContext.h"
-#include "FileSessionGatewayComponent.h"
-#include "Config.h"
-
-using namespace AsteriskSCF::Core::Routing::V1;
-using namespace AsteriskSCF::Core::Discovery::V1;
 using namespace AsteriskSCF::System::Component::V1;
 using namespace AsteriskSCF::System::Logging;
-using namespace AsteriskSCF::SessionCommunications::V1;
-using namespace AsteriskSCF::System::Configuration::V1;
 using namespace std;
 
 namespace AsteriskSCF
@@ -71,29 +70,198 @@ public:
         manageBackplaneService(wrapServiceForRegistration(proxy, category));
     }
 
+    void onActivated()
+    {
+        mEndpointLocatorFeature->getLocator()->updateReplicator(mReplicator);
+    }
+
+    void onStandby()
+    {
+        //
+        // Nil'ing out the replicator object will stop an
+        // further replication.
+        //
+        mEndpointLocatorFeature->getLocator()->updateReplicator(ReplicatorSmartProxy());
+    }
+
     void createReplicationStateListeners()
     {
+        //
+        // Listener is created in startListening for now.. a little different
+        // than other implementations. It is implemented this way mostly to
+        // experiment with an alternate approach to handling the listener
+        // lifetime and moving to and from the standby state.
+        //
     }
     
     void stopListeningToStateReplicators()
     {
+        boost::mutex::scoped_lock lock(mReplicationStateMutex);
+        if (!mReceivingReplicationUpdates)
+        {
+            //
+            // We aren't listening, so we can just exit early.
+            //
+            return;
+        }
+        mReceivingReplicationUpdates = false;
+
+        //
+        // This will cause the object to be "destroyed" with respect to the
+        // object adapter. Since the components affected by the replication
+        // listeners are passive relative to the listener (ie. they don't know
+        // about the listener, the listener knows about them .. sort of)
+        //
+        mReplicationListener->destroy();
+        mReplicationListener = 0;
     }
 
     void listenToStateReplicators()
     {
+        if (getReplicationContext()->getState() != AsteriskSCF::Replication::STANDBY_IN_REPLICA_GROUP)
+        {
+            //
+            // The code is setup so it does two locks. While suboptimal it
+            // prevents us having to have an RPC while holding a lock. This
+            // isn't a performance critical method so this should be ok.
+            //
+            {
+                //
+                // Check to see if we are already wired up and if so, exit early.
+                //
+                boost::mutex::scoped_lock lock(mReplicationStateMutex);
+                if (mReceivingReplicationUpdates)
+                {
+                    return;
+                }
+            }
+
+            //
+            // This is a little different that how some of the other services
+            // are setup because the listener is perpetual in those other
+            // implemenations. In this case, we are trying something a bit
+            // different and only creating the listener when it's needed. 
+            //
+            try
+            {
+                AsteriskSCF::Replication::FileSessionGateway::V1::StateReplicatorListenerPtr servant =
+                    AsteriskSCF::FileSessionGtw::ReplicationListener::create(mEndpointLocatorFeature->getLocator(),
+                            getServiceAdapter(), mLogger);
+                mReplicatorListenerProxy = 
+                    AsteriskSCF::Replication::FileSessionGateway::V1::StateReplicatorListenerPrx::uncheckedCast(
+                        getServiceAdapter()->addWithUUID(servant));
+                try
+                {
+                    mReplicatorListenerProxy = 
+                        AsteriskSCF::Replication::FileSessionGateway::V1::StateReplicatorListenerPrx::uncheckedCast(
+                            mReplicatorListenerProxy->ice_oneway());
+                }
+                catch (const Ice::NoEndpointException&)
+                {
+                    //
+                    // If this exception is thrown it simply means that oneways
+                    // cannot be supported, mReplicatorListenerProxy's original
+                    // value will not be affected.
+                    //
+                }
+            }
+            catch (const std::exception& ex)
+            {
+                mLogger(Error) << "Unable to instantiate replication listener in " << getName() << ": " << ex.what();
+            }
+            catch (...)
+            {
+                mLogger(Error) << "Unable to instantiate replication listener in " << getName() << " (unknown exception).";
+            }
+
+            //
+            // Find the replication service.
+            //
+            try
+            {
+                assert(mReplicator);
+                mReplicator->addListener(mReplicatorListenerProxy);
+                boost::mutex::scoped_lock lock(mReplicationStateMutex);
+                mReceivingReplicationUpdates = true;
+            }
+            catch (const std::exception& ex)
+            {
+                mLogger(Error) << "Unable to add listener to replication server: " << ex.what();
+                throw;
+            }
+        }
     }
 
     void createPrimaryServices()
     {
+        mEndpointLocatorFeature = createEndpointLocatorFeature(getName(), getServiceAdapter());
     }
 
     void findRemoteServices()
     {
+        //
+        // If we are in a situation where replication is supported/required, locate the
+        // replicator.
+        //
+        if (getReplicationContext()->getState() != AsteriskSCF::Replication::ACTIVE_STANDALONE)
+        {
+            AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr replicatorParams = 
+                new AsteriskSCF::Core::Discovery::V1::ServiceLocatorParams;
+            replicatorParams->category = AsteriskSCF::Replication::FileSessionGateway::V1::StateReplicatorDiscoveryCategory;
+            replicatorParams->service = getCommunicator()->getProperties()->getPropertyWithDefault(
+                getName() + ".StateReplicatorService", "default");
+            replicatorParams->id = getCommunicator()->getProperties()->getPropertyWithDefault(
+                getName() + ".StateReplicatorId", "");
+            try
+            {
+                mReplicator = AsteriskSCF::FileSessionGtw::ReplicatorSmartProxy(getServiceLocator(), replicatorParams,
+                    mLogger);
+            }
+            catch (const AsteriskSCF::Core::Discovery::V1::ServiceNotFound&)
+            {
+                mLogger(Error) << getName() << ": unable to get replicator from service locator. Please check configuration.";
+                throw;
+            }
+        }
     }
 
     void preparePrimaryServicesForDiscovery()
     {
+        mEndpointLocatorProxy = AsteriskSCF::Core::Routing::V1::EndpointLocatorPrx::uncheckedCast(
+            mEndpointLocatorFeature->activate(getServiceAdapter()));
+    }
+
+    void registerWithRemoteRemoteServices()
+    {
+        if (mEndpointLocatorFeature)
+        {
+            AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr routerParams = 
+                new AsteriskSCF::Core::Discovery::V1::ServiceLocatorParams;
+            routerParams->category = AsteriskSCF::Core::Routing::V1::RoutingServiceLocatorRegistryDiscoveryCategory;
+            routerParams->service =getCommunicator()->getProperties()->getPropertyWithDefault(getName() +
+                ".EndpointLocatorRegistry", "default");
+            mEndpointLocatorFeature->makeReady(getServiceLocator(), routerParams);
+        }
+    }
+
+    void unregisterFromRemoteServices()
+    {
+        if (mEndpointLocatorFeature)
+        {
+            mEndpointLocatorFeature->suspend();
+        }
     }
+
+private:
+    AsteriskSCF::FileSessionGtw::ReplicatorSmartProxy mReplicator;
+    AsteriskSCF::Replication::FileSessionGateway::V1::StateReplicatorListenerPrx mReplicatorListenerProxy;
+    AsteriskSCF::FileSessionGtw::ReplicationListenerPtr mReplicationListener;
+
+    boost::mutex mReplicationStateMutex;
+    bool mReceivingReplicationUpdates;
+
+    EndpointLocatorFeaturePtr mEndpointLocatorFeature;
+    AsteriskSCF::Core::Routing::V1::EndpointLocatorPrx mEndpointLocatorProxy;
 };
 
 }; // end FileSessionGtw
diff --git a/src/ComponentDefs.h b/src/ComponentDefs.h
new file mode 100644
index 0000000..4e4116f
--- /dev/null
+++ b/src/ComponentDefs.h
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/thread/locks.hpp>
+#include <AsteriskSCF/Discovery/SmartProxy.h>
+#include <AsteriskSCF/Replication/FileSessionGateway/FileSessionReplicationIf.h>
+
+namespace AsteriskSCF
+{
+namespace FileSessionGtw
+{
+
+/**
+ * Some simple typedefs to abbreviate code a bit. Arguably makes it
+ * a bit more readable too.
+ */
+typedef boost::unique_lock<boost::shared_mutex> UniqueLock;
+typedef boost::shared_lock<boost::shared_mutex> SharedLock;
+
+typedef AsteriskSCF::Discovery::SmartProxy<AsteriskSCF::Replication::FileSessionGateway::V1::StateReplicatorPrx>
+    ReplicatorSmartProxy;
+
+} /* End of namespace FileSessionGtw */
+} /* End of namespace AsteriskSCF */
+
diff --git a/src/ComponentFeature.h b/src/ComponentFeature.h
index 1359881..ad5c820 100644
--- a/src/ComponentFeature.h
+++ b/src/ComponentFeature.h
@@ -44,7 +44,13 @@ public:
     /**
      * make final preparations.
      */
-    virtual void makeReady(const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& locator) = 0;
+    virtual void makeReady(const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& locator,
+        const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr& params) = 0;
+
+    /**
+     *
+     */
+    virtual void suspend() = 0;
 };
 
 typedef IceUtil::Handle<ComponentFeature> ComponentFeaturePtr;
diff --git a/src/Configuration.cpp b/src/Configuration.cpp
index a6d5fd2..6457046 100644
--- a/src/Configuration.cpp
+++ b/src/Configuration.cpp
@@ -17,6 +17,8 @@
 #include "Configuration.h"
 #include "Config.h"
 
+#include "EndpointLocator.h"
+
 #include <AsteriskSCF/Configuration/FileSessionGateway/FileSessionGatewayConfigurationIf.h>
 #include <AsteriskSCF/logger.h>
 #include <AsteriskSCF/System/Component/ConfigurationIf.h>
@@ -34,23 +36,61 @@ namespace
     class ConfigurationImpl : public AsteriskSCF::System::Configuration::V1::ConfigurationService
     {
     public:
-        ConfigurationImpl()
+        ConfigurationImpl(const EndpointLocatorImplPtr& endpointLocator) :
+            mEndpointLocator(endpointLocator)
         {
         }
 
-        ConfigurationGroupSeq getConfiguration(const ConfigurationGroupSeq&, const Ice::Current&)
+        ConfigurationGroupSeq getConfiguration(const ConfigurationGroupSeq& groups, const Ice::Current&)
         {
-            return ConfigurationGroupSeq();
+            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;
         }
 
         ConfigurationGroupSeq getConfigurationAll(const ConfigurationGroupSeq&, const Ice::Current&)
         {
-            return ConfigurationGroupSeq();
+            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);
+                result.push_back(endpointGroup);
+                if (endpointGroup)
+                {
+                    EndpointGroupPtr group = new EndpointGroup;
+                    group->id = mEndpointLocator->getId();
+                    EndpointImplSeq impls = mEndpointLocator->getEndpoints();
+                    for (EndpointImplSeq::const_iterator endpointIter = impls.begin(); endpointIter != impls.end(); ++impls)
+                    {
+                        EndpointSpecificationPtr spec = (*endpointIter)->getSpecification();
+                        //
+                        // XXX translate spec to configuration information.
+                        //
+                    }
+                }
+            }
+            return result;
         }
 
         ConfigurationGroupSeq getConfigurationGroups(const Ice::Current&)
         {
-            return ConfigurationGroupSeq();
+            ConfigurationGroupSeq groups;
+            EndpointGroupPtr group = new EndpointGroup;
+            group->id = mEndpointLocator->getId(); 
+            groups.push_back(group);
+            return groups;
         }
 
         void setConfiguration(const ConfigurationGroupSeq&, const Ice::Current&)
@@ -64,6 +104,8 @@ namespace
         void removeConfigurationGroups(const ConfigurationGroupSeq&, const Ice::Current&)
         {
         }
+    private:
+        EndpointLocatorImplPtr mEndpointLocator;
     };
     typedef IceUtil::Handle<ConfigurationImpl> ConfigurationImplPtr;
 
@@ -104,9 +146,17 @@ namespace
             }
         }
 
-        void makeReady(const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& /* locator */)
+        void makeReady(const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& /* locator */,
+            const AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsPtr& /* params */)
+        {
+            // XXX
+        }
+
+        void suspend()
         {
+            //
             // XXX
+            //
         }
 
     private:
diff --git a/src/CookieManager.cpp b/src/CookieManager.cpp
new file mode 100644
index 0000000..701d7c9
--- /dev/null
+++ b/src/CookieManager.cpp
@@ -0,0 +1,142 @@
+/*
+ * 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 "CookieManager.h"
+
+using namespace AsteriskSCF::SessionCommunications::V1;
+
+namespace AsteriskSCF
+{
+namespace FileSessionGtw
+{
+
+class DummyCookieListener : public CookieManagerListener
+{
+public:
+    void cookiesSet(const SessionCookies&)
+    {
+        //
+        // No op.
+        //
+    }
+        
+    void cookiesRemoved(const SessionCookies&)
+    {
+        //
+        // No op.
+        //
+    }
+};
+
+}
+}
+
+using namespace AsteriskSCF::FileSessionGtw;
+
+CookieManager::CookieManager(const CookieManagerListenerPtr& listener) :
+    mListener(listener)
+{
+    //
+    // If no listener is given, one will be provided..
+    //
+    if (!listener)
+    {
+        mListener.reset(new DummyCookieListener);
+    }
+}
+
+void CookieManager::setCookies(const SessionCookies& cookies)
+{
+    {
+        UniqueLock lock(mLock);
+        for (SessionCookies::const_iterator lookingFor = cookies.begin(); 
+             lookingFor != cookies.end(); ++lookingFor)
+        {
+            bool found = false;
+            for (SessionCookies::iterator myCookie = mCookies.begin(); 
+                 myCookie != mCookies.end(); ++myCookie)
+            {
+                //
+                // Cookies of matching id's are replaced, not simply appended
+                // to the cookie sequence.
+                //
+                if ((*lookingFor)->ice_id() == (*myCookie)->ice_id())
+                {
+                    *myCookie = *lookingFor;
+                    found = true;
+                    break;
+                }
+            }
+            if (!found)
... 2591 lines suppressed ...


-- 
asterisk-scf/integration/file_session_gateway.git



More information about the asterisk-scf-commits mailing list