[asterisk-scf-commits] asterisk-scf/integration/bridging.git branch "sessioncontroller" updated.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Sat Jul 23 18:05:35 CDT 2011


branch "sessioncontroller" has been updated
       via  be1cf03fbabd7a5e9c93f4cde070d688562a8089 (commit)
       via  3c850a0aaeb5fec5cde630553739617d12db73f6 (commit)
       via  86a6f6f8caca445fd5a4943a35112d71fa19a63d (commit)
       via  ce9188327600549052e8a0b7e8355f3edce381de (commit)
       via  047ee561b2c0b574bd8bd20c19b84256289481f5 (commit)
       via  f0dc7e12a97094afa58cca73e98afaf70ec33394 (commit)
       via  b0ed098755f70b5ccd942d79547edf1d926bf78a (commit)
      from  efb149a5e3937f8db08d9e057286f7a99be8fca1 (commit)

Summary of changes:
 config/test_bridging.conf                          |    1 +
 .../BridgeService/BridgeReplicatorIf.ice           |    2 +
 src/BridgeImpl.cpp                                 |  254 +++++++++++++++-
 src/BridgeListenerMgr.cpp                          |   16 +-
 src/BridgeListenerMgr.h                            |   10 +-
 src/MediaSplicer.cpp                               |  124 +++++---
 src/MediaSplicer.h                                 |    5 +
 src/Service.cpp                                    |   39 ++--
 src/SessionOperations.cpp                          |  119 ++++++++
 src/SessionOperations.h                            |   39 +++
 src/SessionWrapper.cpp                             |   23 ++
 src/SessionWrapper.h                               |   13 +
 test/BridgeListenerI.cpp                           |   65 +++--
 test/BridgeListenerI.h                             |   26 ++-
 test/CMakeLists.txt                                |    2 +
 test/TestBridging.cpp                              |  304 ++++++++++++++++++++
 test/TestCookieIf.ice                              |   54 ++++
 17 files changed, 978 insertions(+), 118 deletions(-)
 create mode 100644 test/TestCookieIf.ice


- Log -----------------------------------------------------------------
commit be1cf03fbabd7a5e9c93f4cde070d688562a8089
Author: Joshua Colp <jcolp at digium.com>
Date:   Sat Jul 23 20:07:01 2011 -0300

    Add support for removing media streams mid-session.

diff --git a/src/BridgeImpl.cpp b/src/BridgeImpl.cpp
index 890e388..b446609 100755
--- a/src/BridgeImpl.cpp
+++ b/src/BridgeImpl.cpp
@@ -78,7 +78,6 @@ public:
     // AsteriskSCF::SessionCommunications::Bridging::Bridge Interface
     //
     void addSessions_async(const AMD_Bridge_addSessionsPtr& callback, const SessionSeq& sessions, const Ice::Current&);
-    void removeSessions(const SessionSeq& sessions, const Ice::Current& current);
     void removeSessions_async(const AMD_Bridge_removeSessionsPtr& callback, const SessionSeq& sessions,
             const Ice::Current&);
 
diff --git a/src/MediaSplicer.cpp b/src/MediaSplicer.cpp
index 9b21f3b..f3e16a7 100755
--- a/src/MediaSplicer.cpp
+++ b/src/MediaSplicer.cpp
@@ -73,6 +73,7 @@ struct MediaConnectorBuilder : public IceUtil::Shared
     MediaConnectorIPtr connector;
     OutgoingPairings outgoingPairings;
     IncomingPairings incomingPairings;
+    std::map<std::string, std::string> connections;
 };
 typedef IceUtil::Handle<MediaConnectorBuilder> MediaConnectorBuilderPtr;
 
@@ -163,7 +164,7 @@ public:
     }
 
     void update(const MediaConnectorPtr& peer, const OutgoingPairings& outgoing,
-            const IncomingPairings& incoming)
+                const IncomingPairings& incoming, const std::map<std::string, std::string>& connections)
     {
         mLogger(Debug) << FUNLOG << ": establishing a new peer connection.";
         SessionPairingPtr currentState;
@@ -172,6 +173,7 @@ public:
             mPeer = peer;
             mOutgoing = outgoing;
             mIncoming = incoming;
+            mConnections = connections;
             currentState = createUpdate();
         }
         pushUpdate(currentState);
@@ -360,6 +362,11 @@ public:
         return mStreams;
     }
 
+    std::map<std::string, std::string> connections()
+    {
+        return mConnections;
+    }
+
 private:
     boost::shared_mutex mLock;
     vector<OutgoingPairing> mOutgoing;
@@ -373,6 +380,7 @@ private:
     Ice::Long mRepCounter;
     ReplicatorSmartPrx mReplicator;
     Logger mLogger;
+    std::map<std::string, std::string> mConnections;
 };
 
 QueuedTasks createMediaConnectTasks(const SessionWrapperPtr& session, 
@@ -405,7 +413,7 @@ public:
         //
         if (data->peer)
         {
-            data->peer->update(connector, data->outgoingPairings, data->incomingPairings);
+            data->peer->update(connector, data->outgoingPairings, data->incomingPairings, data->connections);
         }
         connector->initialUpdate();
         boost::unique_lock<boost::shared_mutex> lock(mLock);
@@ -486,7 +494,8 @@ public:
 
     void findCompatiblePairings(const StreamInformationDict& streams, vector<OutgoingPairing>& outgoing,
                                 vector<IncomingPairing>& incoming,
-                                MediaConnectorIPtr connector)
+                                MediaConnectorIPtr connector,
+                                std::map<std::string, std::string>& connections)
     {
         // If no streams are present we can not establish any pairings
         if (streams.empty())
@@ -516,11 +525,20 @@ public:
                  stream != streams.end();
                  ++stream)
             {
+                if (stream->second->state == Removed)
+                {
+                    continue;
+                }
 
                 for (StreamInformationDict::const_iterator theirStream = theirStreams.begin();
                      theirStream != theirStreams.end();
                      ++theirStream)
                 {
+                    if (theirStream->second->state == Removed)
+                    {
+                        continue;
+                    }
+
                     // Is this stream compatible with the other stream?
                     if (haveCommonFormats(stream->second, theirStream->second) == false)
                     {
@@ -545,6 +563,9 @@ public:
 			theirStream->second->sinks.pop_back();
                     }
 
+		    // Record this stream connection
+		    connections.insert(make_pair(theirStream->first, stream->first));
+
                     // This stream has been connected so no longer consider it
                     theirStreams.erase(theirStream->first);
                     break;
@@ -660,7 +681,8 @@ public:
 protected:
     bool executeImpl()
     {
-	mSplicer->findCompatiblePairings(mMaterials->streams, mMaterials->outgoingPairings, mMaterials->incomingPairings, mMaterials->connector);
+	mSplicer->findCompatiblePairings(mMaterials->streams, mMaterials->outgoingPairings, mMaterials->incomingPairings,
+                                         mMaterials->connector, mMaterials->connections);
         return true;
     }
 
@@ -807,7 +829,7 @@ protected:
         {
             if (mMaterials->connector)
             {
-                mMaterials->connector->update(mMaterials->peer, mMaterials->outgoingPairings, mMaterials->incomingPairings);
+                mMaterials->connector->update(mMaterials->peer, mMaterials->outgoingPairings, mMaterials->incomingPairings, mMaterials->connections);
             }
             mListener->succeeded();
         }
@@ -829,7 +851,7 @@ protected:
         {
             if (mMaterials->connector)
             {
-                mMaterials->connector->update(mMaterials->peer, mMaterials->outgoingPairings, mMaterials->incomingPairings);
+                mMaterials->connector->update(mMaterials->peer, mMaterials->outgoingPairings, mMaterials->incomingPairings, mMaterials->connections);
             }
             mListener->succeeded();
         }
diff --git a/src/MediaSplicer.h b/src/MediaSplicer.h
index e00b2a9..31b3f19 100644
--- a/src/MediaSplicer.h
+++ b/src/MediaSplicer.h
@@ -72,6 +72,11 @@ public:
      * Replication support function.
      **/
     virtual void update(const AsteriskSCF::Replication::BridgeService::V1::SessionPairingPtr& update) = 0;
+
+    /**
+     * Return connection information.
+     */
+    virtual std::map<std::string, std::string> connections() = 0;
 };
 typedef IceUtil::Handle<MediaConnector> MediaConnectorPtr;
  
diff --git a/src/SessionOperations.cpp b/src/SessionOperations.cpp
index 5982413..75a74ab 100644
--- a/src/SessionOperations.cpp
+++ b/src/SessionOperations.cpp
@@ -172,7 +172,50 @@ void RemoveStreamsOperation::operator()(const SessionWrapperPtr& session)
         return;
     }
 
-    SessionPrx s = session->getSession();
+    AsteriskSCF::Media::V1::StreamInformationDict remove;
+    std::map<std::string, std::string> connections = session->connections();
+
+    // Determine the streams we actually need to remove
+    for (AsteriskSCF::Media::V1::StreamInformationDict::const_iterator stream = mStreams.begin();
+	 stream != mStreams.end();
+	 ++stream)
+    {
+	std::map<std::string, std::string>::const_iterator connection = connections.find(stream->first);
+
+	if (connection != connections.end())
+	{
+	    remove.insert(make_pair(connection->second, new AsteriskSCF::Media::V1::StreamInformation()));
+	}
+    }
+
+    if (remove.empty())
+    {
+        return;
+    }
+
+    SessionControllerPrx controller = session->getSessionController();
+
+    if (!controller)
+    {
+        return;
+    }
+
+    controller->begin_removeStreams(remove, newCallback_SessionController_removeStreams(this,
+                                                                                        &RemoveStreamsOperation::removed,
+                                                                                        &RemoveStreamsOperation::failed),
+                                    session);
 
     mIgnore = true;
 }
+
+void RemoveStreamsOperation::removed(const SessionWrapperPtr& session)
+{
+    session->unplugMedia();
+    mSelf->unplugMedia();
+    session->setupMedia();
+    mSelf->setupMedia();
+}
+
+void RemoveStreamsOperation::failed(const Ice::Exception& ex, const SessionWrapperPtr& session)
+{
+}
diff --git a/src/SessionOperations.h b/src/SessionOperations.h
index 466476d..b3b932d 100644
--- a/src/SessionOperations.h
+++ b/src/SessionOperations.h
@@ -99,7 +99,7 @@ private:
 
 typedef IceUtil::Handle<AddStreamsOperation> AddStreamsOperationPtr;
 
-class RemoveStreamsOperation : public std::unary_function<SessionWrapperPtr, void>
+class RemoveStreamsOperation : public std::unary_function<SessionWrapperPtr, void>, public Ice::Object
 {
 public:
     RemoveStreamsOperation(const SessionWrapperPtr& self,
@@ -107,6 +107,9 @@ public:
     
     void operator()(const SessionWrapperPtr& session);
 
+    void removed(const SessionWrapperPtr& session);
+    void failed(const Ice::Exception& ex, const SessionWrapperPtr& session);
+
 private:
     SessionWrapperPtr mSelf;
     AsteriskSCF::Media::V1::StreamInformationDict mStreams;
diff --git a/src/SessionWrapper.cpp b/src/SessionWrapper.cpp
index b42df0e..1178f5e 100644
--- a/src/SessionWrapper.cpp
+++ b/src/SessionWrapper.cpp
@@ -579,6 +579,16 @@ string SessionWrapper::id()
     return mId;
 }
 
+std::map<std::string, std::string> SessionWrapper::connections()
+{
+    if (mConnector)
+    {
+	return mConnector->connections();
+    }
+
+    return std::map<std::string, std::string>();
+}
+
 void SessionWrapper::setup()
 {
     mLogger(Debug) << FUNLOG << ": starting setup of connected session " << mId;
diff --git a/src/SessionWrapper.h b/src/SessionWrapper.h
index 7c97abf..0bdef83 100644
--- a/src/SessionWrapper.h
+++ b/src/SessionWrapper.h
@@ -124,6 +124,8 @@ public:
 
     std::string id();
 
+    std::map<std::string, std::string> connections();
+
     //
     // Large scale macro operations. In effect the wrapper becomes a sub-component within the bridge.
     //

commit 3c850a0aaeb5fec5cde630553739617d12db73f6
Merge: 86a6f6f ce91883
Author: Joshua Colp <jcolp at digium.com>
Date:   Sat Jul 23 18:58:25 2011 -0300

    Merge branch 'master' into sessioncontroller
    
    Conflicts:
    	src/BridgeImpl.cpp

diff --cc src/BridgeImpl.cpp
index 8672ac4,a9cd9e1..890e388
--- a/src/BridgeImpl.cpp
+++ b/src/BridgeImpl.cpp
@@@ -672,8 -562,7 +691,9 @@@ void BridgeImpl::addSessions_async(cons
          SessionsTrackerPtr tracker(new SessionsTracker);
          QueuedTasks tasks;
          tasks.push_back(new SetBridgeTask(mSessions, mPrx, mSessionListenerPrx, sessions, tracker));
-         tasks.push_back(new AddToListeners(mListeners, tracker));
++	tasks.push_back(new SetAndGetSessionControllerTask(mObjAdapter, mSessions, sessions, this));
+         tasks.push_back(new AddToListeners(mListeners, tracker, getCookies()));
 +	tasks.push_back(new SetAndGetSessionControllerTask(mObjAdapter, mSessions, sessions, this));
          tasks.push_back(new GenericAMDCallback<AMD_Bridge_addSessionsPtr>(callback, tracker));
          tasks.push_back(new UpdateTask(this));
          ExecutorPtr executor(new Executor(tasks, mLogger));
@@@ -924,10 -819,14 +950,15 @@@ void BridgeImpl::replaceSession_async(c
          
          SessionsTrackerPtr tracker(new SessionsTracker);
          QueuedTasks tasks;
-         tasks.push_back(new RemoveSessionsNotify(mListeners, removeTracker));
+         BridgeCookies cookies;
+         {
+             boost::shared_lock<boost::shared_mutex> lock(mLock);
+             cookies = getCookies();
+         }
+         tasks.push_back(new RemoveSessionsNotify(mListeners, removeTracker, cookies));
          tasks.push_back(new SetBridgeTask(mSessions, mPrx, mSessionListenerPrx, newSessions, tracker));
-         tasks.push_back(new AddToListeners(mListeners, tracker));
+         tasks.push_back(new AddToListeners(mListeners, tracker, cookies));
 +	tasks.push_back(new SetAndGetSessionControllerTask(mObjAdapter, mSessions, newSessions, this));
          tasks.push_back(new GenericAMDCallback<AMD_Bridge_replaceSessionPtr>(callback, tracker));
          tasks.push_back(new UpdateTask(this));
          ExecutorPtr executor(new Executor(tasks, mLogger));
@@@ -1075,8 -1036,7 +1168,8 @@@ void BridgeImpl::getAddSessionsTasks(Qu
  {
      SessionsTrackerPtr tracker(new SessionsTracker);
      tasks.push_back(new SetBridgeTask(mSessions, mPrx, mSessionListenerPrx, sessions, tracker));
-     tasks.push_back(new AddToListeners(mListeners, tracker));
+     tasks.push_back(new AddToListeners(mListeners, tracker, getCookies()));
 +    tasks.push_back(new SetAndGetSessionControllerTask(mObjAdapter, mSessions, sessions, this));
      tasks.push_back(new UpdateTask(this));
  }
  

commit 86a6f6f8caca445fd5a4943a35112d71fa19a63d
Author: Joshua Colp <jcolp at digium.com>
Date:   Sat Jul 23 18:56:59 2011 -0300

    Add SessionController support with the ability to add streams mid-session.

diff --git a/src/BridgeImpl.cpp b/src/BridgeImpl.cpp
index f669b40..8672ac4 100755
--- a/src/BridgeImpl.cpp
+++ b/src/BridgeImpl.cpp
@@ -365,6 +365,135 @@ private:
     SessionsTrackerPtr mTracker;
 };
 
+class BridgeSessionController : public SessionController
+{
+public:
+    BridgeSessionController(const BridgeImplPtr& bridge,
+                            const SessionWrapperPtr& self) : mBridge(bridge), mSelf(self) { }
+
+    void changeStreamStates_async(const AsteriskSCF::SessionCommunications::V1::AMD_SessionController_changeStreamStatesPtr& cb,
+                                  const AsteriskSCF::Media::V1::StreamStateDict&, const Ice::Current&)
+    {
+        // We do not care about stream state changes at this point in time
+        cb->ice_response();
+    }
+
+    void addStreams_async(const AsteriskSCF::SessionCommunications::V1::AMD_SessionController_addStreamsPtr& cb,
+                          const AsteriskSCF::Media::V1::StreamInformationDict& streams, const Ice::Current&)
+    {
+        AddStreamsOperationPtr op = new AddStreamsOperation(cb, mSelf, streams);
+        mBridge->getSessions()->visitSessions(*op);
+    }
+
+    void removeStreams_async(const AsteriskSCF::SessionCommunications::V1::AMD_SessionController_removeStreamsPtr& cb,
+                             const AsteriskSCF::Media::V1::StreamInformationDict& streams, const Ice::Current&)
+    {
+        RemoveStreamsOperation op(mSelf, streams);
+        mBridge->getSessions()->visitSessions(op);
+        cb->ice_response();
+    }
+
+private:
+    BridgeImplPtr mBridge;
+    SessionWrapperPtr mSelf;
+};
+
+class SetAndGetSessionControllerTask : public QueuedTask
+{
+public:
+    SetAndGetSessionControllerTask(const Ice::ObjectAdapterPtr& adapter,
+                                   const SessionCollectionPtr& sessionCollection,
+                                   const SessionSeq& sessions,
+                                   const BridgeImplPtr& bridge):
+        QueuedTask("SetAndGetSessionControllerTask"),
+        mAdapter(adapter),
+        mSessionManager(sessionCollection),
+        mSessions(sessions),
+        mTracker(new SessionsTracker()),
+        mBridge(bridge)
+        {
+        }
+
+protected:
+    bool executeImpl()
+    {
+        bool tasksDispatched = false;
+        for (SessionSeq::iterator i = mSessions.begin(); i != mSessions.end(); ++i)
+        {
+            SessionWrapperPtr session = mSessionManager->getSession(*i);
+            if (session == 0)
+            {
+                //
+                // This shouldn't happen!
+                //
+                mTracker->addExceptionMessage(*i, "session not found");
+                continue;
+            }
+            tasksDispatched = true;
+            SessionControllerPtr controller = new BridgeSessionController(mBridge, session);
+	    std::string identity = (*i)->ice_getIdentity().name;
+	    identity += ".bridgecontroller";
+	    SessionControllerPrx controllerPrx =
+		SessionControllerPrx::uncheckedCast(mAdapter->add(controller, mAdapter->getCommunicator()->stringToIdentity(identity)));
+	    (*i)->begin_setAndGetSessionController(controllerPrx, newCallback_Session_setAndGetSessionController(this,
+                                                   &SetAndGetSessionControllerTask::get, &SetAndGetSessionControllerTask::failed), session);
+        }
+        return !tasksDispatched;
+    }
+
+    void get(const SessionControllerPrx& controller, const SessionWrapperPtr& session)
+    {
+        session->setSessionController(controller);
+        mTracker->add(session->getSession());
+        if (mTracker->responseCount() == mSessions.size())
+        {
+            mListener->succeeded();
+        }
+    }
+
+    void failed(const Ice::Exception& ex, const SessionWrapperPtr& session)
+    {
+        //
+        // TODO:
+        // * Log exception.
+        // * Rollback
+        // * Interpret exception and decide whether or not to fail the entire operations.
+        // Currently the semantics allow some operations to fail.
+        //
+        mTracker->addException(session->getSession(), ex);
+        try
+        {
+            //
+            // We want to make sure that session is laying around. The session collection will
+            // take care of cleaning it up as long as it is marked as destroyed.
+            //
+            session->destroy();
+        }
+        catch(...)
+        {
+        }
+        if (mTracker->responseCount() == mSessions.size())
+        {
+            SessionErrorSeq exceptions = mTracker->getExceptions();
+            if (exceptions.size() == mSessions.size())
+            {
+                mListener->failed();
+            }
+            else
+            {
+                mListener->succeeded();
+            }
+        }
+    }
+    
+private:
+    Ice::ObjectAdapterPtr mAdapter;
+    SessionCollectionPtr mSessionManager;
+    SessionSeq mSessions;
+    SessionsTrackerPtr mTracker;
+    BridgeImplPtr mBridge;
+};
+
 class AddToListeners : public QueuedTask
 {
 public:
@@ -544,6 +673,7 @@ void BridgeImpl::addSessions_async(const AMD_Bridge_addSessionsPtr& callback, co
         QueuedTasks tasks;
         tasks.push_back(new SetBridgeTask(mSessions, mPrx, mSessionListenerPrx, sessions, tracker));
         tasks.push_back(new AddToListeners(mListeners, tracker));
+	tasks.push_back(new SetAndGetSessionControllerTask(mObjAdapter, mSessions, sessions, this));
         tasks.push_back(new GenericAMDCallback<AMD_Bridge_addSessionsPtr>(callback, tracker));
         tasks.push_back(new UpdateTask(this));
         ExecutorPtr executor(new Executor(tasks, mLogger));
@@ -797,6 +927,7 @@ void BridgeImpl::replaceSession_async(const AMD_Bridge_replaceSessionPtr& callba
         tasks.push_back(new RemoveSessionsNotify(mListeners, removeTracker));
         tasks.push_back(new SetBridgeTask(mSessions, mPrx, mSessionListenerPrx, newSessions, tracker));
         tasks.push_back(new AddToListeners(mListeners, tracker));
+	tasks.push_back(new SetAndGetSessionControllerTask(mObjAdapter, mSessions, newSessions, this));
         tasks.push_back(new GenericAMDCallback<AMD_Bridge_replaceSessionPtr>(callback, tracker));
         tasks.push_back(new UpdateTask(this));
         ExecutorPtr executor(new Executor(tasks, mLogger));
@@ -945,6 +1076,7 @@ void BridgeImpl::getAddSessionsTasks(QueuedTasks& tasks,
     SessionsTrackerPtr tracker(new SessionsTracker);
     tasks.push_back(new SetBridgeTask(mSessions, mPrx, mSessionListenerPrx, sessions, tracker));
     tasks.push_back(new AddToListeners(mListeners, tracker));
+    tasks.push_back(new SetAndGetSessionControllerTask(mObjAdapter, mSessions, sessions, this));
     tasks.push_back(new UpdateTask(this));
 }
 
diff --git a/src/MediaSplicer.cpp b/src/MediaSplicer.cpp
index 7121dfc..9b21f3b 100755
--- a/src/MediaSplicer.cpp
+++ b/src/MediaSplicer.cpp
@@ -355,6 +355,11 @@ public:
         return mKey;
     }
 
+    StreamInformationDict streams()
+    {
+        return mStreams;
+    }
+
 private:
     boost::shared_mutex mLock;
     vector<OutgoingPairing> mOutgoing;
@@ -404,7 +409,7 @@ public:
         }
         connector->initialUpdate();
         boost::unique_lock<boost::shared_mutex> lock(mLock);
-        mSessions.push_back(MediaSessionStruct(data->streams, connector));
+	mConnectors.push_back(connector);
         return connector;
     }
 
@@ -418,13 +423,13 @@ public:
         //
         // Reap.
         //
-        MediaSessions::iterator i = mSessions.begin();
-        while (i != mSessions.end())
+        MediaConnectors::iterator i = mConnectors.begin();
+        while (i != mConnectors.end())
         {
-            if (!i->connector->isConnected())
+            if (!(*i)->isConnected())
             {
                 mLogger(Debug) << FUNLOG << ": reaping a connector";
-                i = mSessions.erase(i);
+                i = mConnectors.erase(i);
                 continue;
             }
             ++i;
@@ -435,9 +440,9 @@ public:
         // one of them is going to have an empty connector.
         //
         MediaConnectorIPtr existing;
-        if (mSessions.size() == 1)
+        if (mConnectors.size() == 1)
         {
-            existing = mSessions.back().connector;
+            existing = mConnectors.back();
             existing->clearConnections();
         }
 
@@ -455,32 +460,33 @@ public:
         boost::unique_lock<boost::shared_mutex> lock(mLock);
         MediaConnectorIPtr result;
 
-        MediaSessions::iterator i = mSessions.begin();
-        while (i != mSessions.end())
+        MediaConnectors::iterator i = mConnectors.begin();
+        while (i != mConnectors.end())
         {
-            if (!i->connector->isConnected())
+            if (!(*i)->isConnected())
             {
                 mLogger(Debug) << FUNLOG << ": reaping a connector";
-                MediaSessions::iterator t = i;
-                i = mSessions.erase(t);
+                MediaConnectors::iterator t = i;
+                i = mConnectors.erase(t);
                 continue;
             }
             ++i;
         }
 
         MediaConnectorPtr existing;
-        if (mSessions.size() == 1)
+        if (mConnectors.size() == 1)
         {
-            existing = mSessions.back().connector;
+            existing = mConnectors.back();
             existing->clearConnections();
         }
         result = new MediaConnectorI(pairings, existing, mReplicator, mLogger);
-        mSessions.push_back(MediaSessionStruct(pairings->streams, result));
+        mConnectors.push_back(result);
         return result;
     }
 
     void findCompatiblePairings(const StreamInformationDict& streams, vector<OutgoingPairing>& outgoing,
-                                vector<IncomingPairing>& incoming)
+                                vector<IncomingPairing>& incoming,
+                                MediaConnectorIPtr connector)
     {
         // If no streams are present we can not establish any pairings
         if (streams.empty())
@@ -490,32 +496,31 @@ public:
 
         boost::shared_lock<boost::shared_mutex> lock(mLock);
 
-        for (MediaSessions::const_iterator i = mSessions.begin(); i != mSessions.end(); ++i)
+        for (MediaConnectors::const_iterator i = mConnectors.begin(); i != mConnectors.end(); ++i)
         {
-            // If no streams are present go ahead and skip it
-            if (i->streams.empty())
+            if ((*i)->id() == connector->id())
             {
                 continue;
             }
 
-            // Create a copy so we can remove streams once pairings have been established for them
-            StreamInformationDict theirStreams = i->streams;
+            StreamInformationDict theirStreams = (*i)->streams();
+
+            // If no streams are present go ahead and skip it
+            if (theirStreams.empty())
+            {
+                continue;
+            }
 
             // Iterate our own streams looking for any that can be connected to this session
             for (StreamInformationDict::const_iterator stream = streams.begin();
                  stream != streams.end();
                  ++stream)
             {
+
                 for (StreamInformationDict::const_iterator theirStream = theirStreams.begin();
                      theirStream != theirStreams.end();
                      ++theirStream)
                 {
-                    // If this is us skip all streams
-                    if (stream->second->sinks.front() == theirStream->second->sinks.front())
-                    {
-                        break;
-                    }
-                    
                     // Is this stream compatible with the other stream?
                     if (haveCommonFormats(stream->second, theirStream->second) == false)
                     {
@@ -556,21 +561,9 @@ private:
     ReplicatorSmartPrx mReplicator;
     Logger mLogger;
 
-    struct MediaSessionStruct
-    {
-        StreamInformationDict streams;
-        MediaConnectorIPtr connector;
-
-        MediaSessionStruct(const StreamInformationDict& strms, const MediaConnectorIPtr& con) :
-            streams(strms),
-            connector(con)
-        {
-        }
-    };
-
-    typedef vector<MediaSessionStruct> MediaSessions;
+    typedef vector<MediaConnectorIPtr> MediaConnectors;
 
-    MediaSessions mSessions;
+    MediaConnectors mConnectors;
 
     bool hasPreferredCodecOverride()
     {
@@ -667,7 +660,7 @@ public:
 protected:
     bool executeImpl()
     {
-	mSplicer->findCompatiblePairings(mMaterials->streams, mMaterials->outgoingPairings, mMaterials->incomingPairings);
+	mSplicer->findCompatiblePairings(mMaterials->streams, mMaterials->outgoingPairings, mMaterials->incomingPairings, mMaterials->connector);
         return true;
     }
 
diff --git a/src/SessionOperations.cpp b/src/SessionOperations.cpp
index 58670a9..5982413 100644
--- a/src/SessionOperations.cpp
+++ b/src/SessionOperations.cpp
@@ -100,3 +100,79 @@ void RelayIndication::operator()(const SessionWrapperPtr& session)
         }
     }
 }
+
+AddStreamsOperation::AddStreamsOperation(const AsteriskSCF::SessionCommunications::V1::AMD_SessionController_addStreamsPtr& cb,
+                                         const SessionWrapperPtr& self,
+                                         const AsteriskSCF::Media::V1::StreamInformationDict& streams) :
+    mCb(cb),
+    mSelf(self),
+    mStreams(streams),
+    mIgnore(false)
+{
+}
+
+void AddStreamsOperation::operator()(const SessionWrapperPtr& session)
+{
+    if (mIgnore == true || mSelf == session)
+    {
+        return;
+    }
+
+    SessionControllerPrx controller = session->getSessionController();
+
+    if (!controller)
+    {
+        return;
+    }
+
+    // Go ahead and request that the streams be added
+    controller->begin_addStreams(mStreams, newCallback_SessionController_addStreams(this,
+                                                                                    &AddStreamsOperation::added,
+                                                                                    &AddStreamsOperation::failed),
+                                 session);
+
+    // We only allow requesting streams on a single session at this point
+    mIgnore = true;
+}
+
+void AddStreamsOperation::added(const AsteriskSCF::Media::V1::StreamInformationDict& streams,
+                                const SessionWrapperPtr& session)
+{
+    // If any streams were added set up media so it flows
+    if (!streams.empty())
+    {
+        session->unplugMedia();
+        mSelf->unplugMedia();
+        session->setupMedia();
+        mSelf->setupMedia();
+    }
+
+    // Now that everything is ready go ahead and respond
+    mCb->ice_response(streams);
+}
+
+void AddStreamsOperation::failed(const Ice::Exception& ex, const SessionWrapperPtr& session)
+{
+    // Since this failed tell the session that initiated this operation that no streams were added
+    mCb->ice_response(AsteriskSCF::Media::V1::StreamInformationDict());
+}
+
+RemoveStreamsOperation::RemoveStreamsOperation(const SessionWrapperPtr& self,
+                                               const AsteriskSCF::Media::V1::StreamInformationDict& streams) :
+    mSelf(self),
+    mStreams(streams),
+    mIgnore(false)
+{
+}
+
+void RemoveStreamsOperation::operator()(const SessionWrapperPtr& session)
+{
+    if (mIgnore == true || mSelf == session)
+    {
+        return;
+    }
+
+    SessionPrx s = session->getSession();
+
+    mIgnore = true;
+}
diff --git a/src/SessionOperations.h b/src/SessionOperations.h
index 97726fc..466476d 100644
--- a/src/SessionOperations.h
+++ b/src/SessionOperations.h
@@ -16,6 +16,7 @@
 #pragma once
 
 #include <AsteriskSCF/SessionCommunications/SessionCommunicationsIf.h>
+#include <AsteriskSCF/Media/MediaIf.h>
 #include <AsteriskSCF/logger.h>
 #include "BridgeReplicatorIf.h"
 #include "SessionWrapper.h"
@@ -77,6 +78,41 @@ private:
     bool mIncludeConnected;
 };
 
+class AddStreamsOperation : public std::unary_function<SessionWrapperPtr, void>, public Ice::Object
+{
+public:
+    AddStreamsOperation(const AsteriskSCF::SessionCommunications::V1::AMD_SessionController_addStreamsPtr& cb,
+                        const SessionWrapperPtr& self,
+                        const AsteriskSCF::Media::V1::StreamInformationDict& streams);
+
+    void operator()(const SessionWrapperPtr& session);
+
+    void added(const AsteriskSCF::Media::V1::StreamInformationDict& streams, const SessionWrapperPtr& session);
+    void failed(const Ice::Exception& ex, const SessionWrapperPtr& session);
+
+private:
+    AsteriskSCF::SessionCommunications::V1::AMD_SessionController_addStreamsPtr mCb;
+    SessionWrapperPtr mSelf;
+    AsteriskSCF::Media::V1::StreamInformationDict mStreams;
+    bool mIgnore;
+};
+
+typedef IceUtil::Handle<AddStreamsOperation> AddStreamsOperationPtr;
+
+class RemoveStreamsOperation : public std::unary_function<SessionWrapperPtr, void>
+{
+public:
+    RemoveStreamsOperation(const SessionWrapperPtr& self,
+                        const AsteriskSCF::Media::V1::StreamInformationDict& streams);
+    
+    void operator()(const SessionWrapperPtr& session);
+
+private:
+    SessionWrapperPtr mSelf;
+    AsteriskSCF::Media::V1::StreamInformationDict mStreams;
+    bool mIgnore;
+};
+
 class IfStateCriteria
 {
 public:
diff --git a/src/SessionWrapper.cpp b/src/SessionWrapper.cpp
index ea9f8fa..b42df0e 100644
--- a/src/SessionWrapper.cpp
+++ b/src/SessionWrapper.cpp
@@ -467,6 +467,19 @@ SessionPrx SessionWrapper::getSession() const
     return mSession->session;
 }
 
+SessionControllerPrx SessionWrapper::getSessionController() const
+{
+    boost::shared_lock<boost::shared_mutex> lock(mLock);
+    return mSessionController;
+}
+
+void SessionWrapper::setSessionController(const AsteriskSCF::SessionCommunications::V1::SessionControllerPrx& controller)
+{
+    boost::unique_lock<boost::shared_mutex> lock(mLock);
+    mSessionController = controller;
+}
+
+
 void SessionWrapper::setupMedia()
 {
     mLogger(Debug) << FUNLOG << " for " << mId;
diff --git a/src/SessionWrapper.h b/src/SessionWrapper.h
index 9ddb43c..7c97abf 100644
--- a/src/SessionWrapper.h
+++ b/src/SessionWrapper.h
@@ -81,6 +81,16 @@ public:
     AsteriskSCF::SessionCommunications::V1::SessionPrx getSession() const;
 
     /**
+     * Accesses the session controller proxy that the session gave us.
+     */
+    AsteriskSCF::SessionCommunications::V1::SessionControllerPrx getSessionController() const;
+
+    /**
+     * Sets the session controller used to control this session.
+     */
+    void setSessionController(const AsteriskSCF::SessionCommunications::V1::SessionControllerPrx&);
+
+    /**
      * Sets the media connector object. This updates the media pairings associated
      * with this session.
      * Initiates replication.
@@ -144,6 +154,7 @@ private:
     std::string mId;
     MediaSplicerPtr mSplicer;
     ExecutorPtr mActivities;
+    AsteriskSCF::SessionCommunications::V1::SessionControllerPrx mSessionController;
 
     /**
      * Sends changes to the replication service. This should never occur

commit ce9188327600549052e8a0b7e8355f3edce381de
Author: Kevin P. Fleming <kpfleming at digium.com>
Date:   Tue Jul 19 13:33:52 2011 -0500

    Resolve compiler warning about size_t/int comparison.

diff --git a/test/TestBridging.cpp b/test/TestBridging.cpp
index 38ecc55..a8052ac 100644
--- a/test/TestBridging.cpp
+++ b/test/TestBridging.cpp
@@ -82,7 +82,7 @@ BridgeCookies bakeTestCookies()
 
 void tasteCookies(const BridgeCookies& cookies, bool a, bool b, bool c, bool d)
 {
-    int count = 0;
+    size_t count = 0;
     if (a)
     {
         ++count;

commit 047ee561b2c0b574bd8bd20c19b84256289481f5
Author: Kevin P. Fleming <kpfleming at digium.com>
Date:   Tue Jul 19 13:33:30 2011 -0500

    Resolve compiler warnings about unused variables.

diff --git a/test/BridgeListenerI.cpp b/test/BridgeListenerI.cpp
index 222995f..8a95767 100644
--- a/test/BridgeListenerI.cpp
+++ b/test/BridgeListenerI.cpp
@@ -81,7 +81,7 @@ bool BridgeListenerI::resetStopped()
 bool BridgeListenerI::waitForAdded(unsigned long milliseconds, AsteriskSCF::SessionCommunications::V1::SessionSeq& added)
 {
     IceUtil::Monitor<IceUtil::Mutex>::Lock lock(mAddMonitor);
-    bool waitResult = mAddMonitor.timedWait(IceUtil::Time::milliSeconds(milliseconds));
+    mAddMonitor.timedWait(IceUtil::Time::milliSeconds(milliseconds));
     added = mAdded;
     mAdded.clear();
     return !added.empty();
@@ -90,11 +90,10 @@ bool BridgeListenerI::waitForAdded(unsigned long milliseconds, AsteriskSCF::Sess
 bool BridgeListenerI::waitForRemoved(unsigned long milliseconds, AsteriskSCF::SessionCommunications::V1::SessionSeq& removed)
 {
     IceUtil::Monitor<IceUtil::Mutex>::Lock lock(mRemoveMonitor);
-    bool waitResult = mRemoveMonitor.timedWait(IceUtil::Time::milliSeconds(milliseconds));
+    mRemoveMonitor.timedWait(IceUtil::Time::milliSeconds(milliseconds));
     removed = mRemoved;
     mRemoved.clear();
     return !removed.empty();
-
 }
 
 bool BridgeListenerI::waitForStopped(unsigned long milliseconds)

commit f0dc7e12a97094afa58cca73e98afaf70ec33394
Author: Joshua Colp <jcolp at digium.com>
Date:   Tue Jul 19 13:14:04 2011 -0300

    Connect all available sources and sinks.

diff --git a/src/MediaSplicer.cpp b/src/MediaSplicer.cpp
index 6263e71..7121dfc 100755
--- a/src/MediaSplicer.cpp
+++ b/src/MediaSplicer.cpp
@@ -522,10 +522,25 @@ public:
                         continue;
                     }
 
-		    // Connect sources and sinks together, right now we only support the first
-		    outgoing.push_back(OutgoingPairing(stream->second->sinks.front(), theirStream->second->sources.front()));
-		    incoming.push_back(IncomingPairing(stream->second->sources.front(), theirStream->second->sinks.front()));
+		    // Connect all available sources and sinks together
+		    StreamSinkSeq sinks = stream->second->sinks;
+		    StreamSourceSeq sources = stream->second->sources;
+
+		    while (!sinks.empty() && !theirStream->second->sources.empty())
+		    {
+                        outgoing.push_back(OutgoingPairing(sinks.back(), theirStream->second->sources.back()));
+			sinks.pop_back();
+			theirStream->second->sources.pop_back();
+                    }
+
+		    while (!sources.empty() && !theirStream->second->sinks.empty())
+                    {
+                        incoming.push_back(IncomingPairing(sources.back(), theirStream->second->sinks.back()));
+			sources.pop_back();
+			theirStream->second->sinks.pop_back();
+                    }
 
+                    // This stream has been connected so no longer consider it
                     theirStreams.erase(theirStream->first);
                     break;
                 }

commit b0ed098755f70b5ccd942d79547edf1d926bf78a
Author: Brent Eagles <beagles at digium.com>
Date:   Thu Jul 14 20:00:56 2011 -0230

    - Bridge cookie support
    
    - Added some component tests for cookie support. These tests may also do a fair
    job of testing unsliceable support, but I'm not at all sure that this is the
    case as everything is run in a single process.
    
    - Also added a workaround in the bridge service for an issue which prevent the
    test suite from running. This is *not* a desirable state of affairs. I think
    that there will be a better solution once the pending changes to service
    discovery are completed.

diff --git a/config/test_bridging.conf b/config/test_bridging.conf
index e88f751..4e19d47 100644
--- a/config/test_bridging.conf
+++ b/config/test_bridging.conf
@@ -105,6 +105,7 @@ ServiceLocatorLocalAdapter.Endpoints=tcp -p 4412
 #
 LocatorService.Proxy=LocatorService:default -p 4411
 ServiceLocatorManagementProxy=LocatorServiceManagement:tcp -p 4422
+LocatorServiceManagement.Proxy=LocatorServiceManagement:tcp -p 4422
 
 #
 # The IceBox entries for loading the services.
diff --git a/slice/AsteriskSCF/Replication/BridgeService/BridgeReplicatorIf.ice b/slice/AsteriskSCF/Replication/BridgeService/BridgeReplicatorIf.ice
index 4b404cb..6f5c177 100644
--- a/slice/AsteriskSCF/Replication/BridgeService/BridgeReplicatorIf.ice
+++ b/slice/AsteriskSCF/Replication/BridgeService/BridgeReplicatorIf.ice
@@ -203,6 +203,8 @@ class BridgeStateItem extends ReplicatedStateItem
     ServiceState runningState;
 
     MediaOperationReplicationPolicy mediaReplicationPolicy;
+
+    AsteriskSCF::SessionCommunications::V1::BridgeCookieDict cookies;
 };
 
 class BridgeListenerStateItem extends ReplicatedStateItem
diff --git a/src/BridgeImpl.cpp b/src/BridgeImpl.cpp
index f669b40..a9cd9e1 100755
--- a/src/BridgeImpl.cpp
+++ b/src/BridgeImpl.cpp
@@ -92,6 +92,10 @@ public:
     void replaceSession_async(const AMD_Bridge_replaceSessionPtr& callbac, const SessionPrx& sessionToReplace,
             const SessionSeq& newSessions, const Ice::Current& current);
 
+    void setCookies(const BridgeCookies& cookies, const Ice::Current&);
+    void removeCookies(const BridgeCookies& cookies, const Ice::Current&);
+    BridgeCookies getCookies(const BridgeCookies& cookies, const Ice::Current&);
+
     //
     // BridgeServant methods
     //
@@ -112,6 +116,16 @@ public:
 
     void getAddSessionsTasks(QueuedTasks& tasks, const SessionSeq& sessions);
 
+    BridgeCookies getCookies()
+    {
+        BridgeCookies result;
+        for (BridgeCookieDict::const_iterator i = mState->cookies.begin(); i != mState->cookies.end(); ++i)
+        {
+            result.push_back(i->second);
+        }
+        return result;
+    }
+
 private:
 
     boost::shared_mutex mLock;
@@ -246,10 +260,11 @@ class RemoveSessionsNotify : public QueuedTask
 {
 public:
     RemoveSessionsNotify(const BridgeListenerMgrPtr& bridgeListeners,
-            const SessionsTrackerPtr& tracker) :
+            const SessionsTrackerPtr& tracker, const BridgeCookies& cookies) :
         QueuedTask("RemoveSessionsNotify"),
         mBridgeListeners(bridgeListeners),
-        mTracker(tracker)
+        mTracker(tracker),
+        mCookies(cookies)
     {
     }
     
@@ -259,7 +274,7 @@ protected:
         SessionSeq sessions = mTracker->getSessions();
         if (!sessions.empty())
         {
-            mBridgeListeners->sessionsRemoved(sessions);
+            mBridgeListeners->sessionsRemoved(sessions, mCookies);
         }
         return true;
     }
@@ -267,6 +282,7 @@ protected:
 private:
     BridgeListenerMgrPtr mBridgeListeners;
     SessionsTrackerPtr mTracker;
+    BridgeCookies mCookies;
 };
 
 class SetBridgeTask : public QueuedTask
@@ -368,23 +384,26 @@ private:
 class AddToListeners : public QueuedTask
 {
 public:
-    AddToListeners(const BridgeListenerMgrPtr& listeners, const SessionsTrackerPtr& tracker) :
+    AddToListeners(const BridgeListenerMgrPtr& listeners, const SessionsTrackerPtr& tracker,
+        const BridgeCookies& cookies) :
         QueuedTask("AddToListeners"),
         mListeners(listeners),
-        mTracker(tracker)
+        mTracker(tracker),
+        mCookies(cookies)
     {
     }
     
 protected:
     bool executeImpl()
     {
-        mListeners->sessionsAdded(mTracker->getSessions());
+        mListeners->sessionsAdded(mTracker->getSessions(), mCookies);
         return true;
     }
     
 private:
     BridgeListenerMgrPtr mListeners;
     SessionsTrackerPtr mTracker;
+    BridgeCookies mCookies;
 };
 
 class CheckShutdown : public QueuedTask
@@ -543,7 +562,7 @@ void BridgeImpl::addSessions_async(const AMD_Bridge_addSessionsPtr& callback, co
         SessionsTrackerPtr tracker(new SessionsTracker);
         QueuedTasks tasks;
         tasks.push_back(new SetBridgeTask(mSessions, mPrx, mSessionListenerPrx, sessions, tracker));
-        tasks.push_back(new AddToListeners(mListeners, tracker));
+        tasks.push_back(new AddToListeners(mListeners, tracker, getCookies()));
         tasks.push_back(new GenericAMDCallback<AMD_Bridge_addSessionsPtr>(callback, tracker));
         tasks.push_back(new UpdateTask(this));
         ExecutorPtr executor(new Executor(tasks, mLogger));
@@ -596,7 +615,13 @@ void BridgeImpl::removeSessions_async(const AMD_Bridge_removeSessionsPtr& callba
             }
         }
         QueuedTasks tasks;
-        tasks.push_back(new RemoveSessionsNotify(mListeners, removed));
+
+        BridgeCookies cookies;
+        {
+            boost::shared_lock<boost::shared_mutex> lock(mLock);
+            cookies = getCookies();
+        }
+        tasks.push_back(new RemoveSessionsNotify(mListeners, removed, cookies));
         tasks.push_back(new GenericAMDCallback<AMD_Bridge_removeSessionsPtr>(callback, removed));
         tasks.push_back(new CheckShutdown(this, mPrx));
         ExecutorPtr runner(new Executor(tasks, mLogger));
@@ -648,7 +673,7 @@ void BridgeImpl::shutdown(const Ice::Current& current)
         }
         mState->runningState = ShuttingDown;
 
-        mListeners->stopping();
+        mListeners->stopping(getCookies());
         update = createUpdate();
     }
     pushUpdate(update);
@@ -661,8 +686,8 @@ void BridgeImpl::shutdown(const Ice::Current& current)
         ResponseCodePtr responseCode = new ResponseCode;
         ShutdownSessionOperation shutdownOp(mSessionListenerPrx, responseCode, mLogger);
         mSessions->visitSessions(shutdownOp);
-        mListeners->stopped();
         boost::unique_lock<boost::shared_mutex> lock(mLock);
+        mListeners->stopped(getCookies());
         mLogger(Info) << objectIdFromCurrent(current) << ": is shutdown." ;
         mState->runningState = Destroyed;
         //
@@ -694,7 +719,7 @@ void BridgeImpl::destroy(const Ice::Current& current)
         }
         mState->runningState = Destroyed;
         mLogger(Info) << objectIdFromCurrent(current) << ": is now destroyed." ;
-        mListeners->stopped();
+        mListeners->stopped(getCookies());
         mSessionListener = 0;
         update = createUpdate();
     }
@@ -794,9 +819,14 @@ void BridgeImpl::replaceSession_async(const AMD_Bridge_replaceSessionPtr& callba
         
         SessionsTrackerPtr tracker(new SessionsTracker);
         QueuedTasks tasks;
-        tasks.push_back(new RemoveSessionsNotify(mListeners, removeTracker));
+        BridgeCookies cookies;
+        {
+            boost::shared_lock<boost::shared_mutex> lock(mLock);
+            cookies = getCookies();
+        }
+        tasks.push_back(new RemoveSessionsNotify(mListeners, removeTracker, cookies));
         tasks.push_back(new SetBridgeTask(mSessions, mPrx, mSessionListenerPrx, newSessions, tracker));
-        tasks.push_back(new AddToListeners(mListeners, tracker));
+        tasks.push_back(new AddToListeners(mListeners, tracker, cookies));
         tasks.push_back(new GenericAMDCallback<AMD_Bridge_replaceSessionPtr>(callback, tracker));
         tasks.push_back(new UpdateTask(this));
         ExecutorPtr executor(new Executor(tasks, mLogger));
@@ -812,6 +842,68 @@ void BridgeImpl::replaceSession_async(const AMD_Bridge_replaceSessionPtr& callba
     }
 }
 
+void BridgeImpl::setCookies(const BridgeCookies& cookies, const Ice::Current& current)
+{
+    mLogger(Debug) << FUNLOG << ":" << objectIdFromCurrent(current);
+    BridgeStateItemPtr update;
+    {
+        boost::unique_lock<boost::shared_mutex> lock(mLock);
+        for (BridgeCookies::const_iterator i = cookies.begin(); i != cookies.end(); ++i)
+        {
+            if ((*i))
+            {
+                mState->cookies[(*i)->ice_id()] = (*i);
+            }
+        }
+        if (!cookies.empty())
+        {
+            update = createUpdate();
+        }
+    }
+    pushUpdate(update);
+}
+
+void BridgeImpl::removeCookies(const BridgeCookies& cookies, const Ice::Current& current)
+{
+    mLogger(Debug) << FUNLOG << ":" << objectIdFromCurrent(current);
+    BridgeStateItemPtr update;
+    {
+        boost::unique_lock<boost::shared_mutex> lock(mLock);
+        bool dirty = false;
+        for (BridgeCookies::const_iterator i = cookies.begin(); i != cookies.end(); ++i)
+        {
+            BridgeCookieDict::iterator v = mState->cookies.find((*i)->ice_id());
+            if (v != mState->cookies.end())
+            {
+                dirty = true;
+                mState->cookies.erase(v);
+            }
+        }
+
+        if (dirty)
+        {
+            update = createUpdate();
+        }
+    }
+    pushUpdate(update);
+}
+
+BridgeCookies BridgeImpl::getCookies(const BridgeCookies& cookies, const Ice::Current& current)
+{
+    BridgeCookies result;
+    mLogger(Debug) << FUNLOG << ":" << objectIdFromCurrent(current);
+    boost::shared_lock<boost::shared_mutex> lock(mLock);
+    for (BridgeCookies::const_iterator i = cookies.begin(); i != cookies.end(); ++i)
+    {
+        BridgeCookieDict::const_iterator v = mState->cookies.find((*i)->ice_id());
+        if (v != mState->cookies.end())
+        {
+            result.push_back(v->second);
+        }
+    }
+    return result;
+}
+
 bool BridgeImpl::destroyed()
 {
     boost::shared_lock<boost::shared_mutex> lock(mLock);
@@ -944,7 +1036,7 @@ void BridgeImpl::getAddSessionsTasks(QueuedTasks& tasks,
 {
     SessionsTrackerPtr tracker(new SessionsTracker);
     tasks.push_back(new SetBridgeTask(mSessions, mPrx, mSessionListenerPrx, sessions, tracker));
-    tasks.push_back(new AddToListeners(mListeners, tracker));
+    tasks.push_back(new AddToListeners(mListeners, tracker, getCookies()));
     tasks.push_back(new UpdateTask(this));
 }
 
diff --git a/src/BridgeListenerMgr.cpp b/src/BridgeListenerMgr.cpp
index 146162e..d4e214f 100644
--- a/src/BridgeListenerMgr.cpp
+++ b/src/BridgeListenerMgr.cpp
@@ -26,22 +26,22 @@ BridgeListenerMgr::BridgeListenerMgr(const Ice::CommunicatorPtr& comm,
 {
 }
 
-void BridgeListenerMgr::sessionsAdded(const SessionSeq& sessions)
+void BridgeListenerMgr::sessionsAdded(const SessionSeq& sessions, const BridgeCookies& cookies)
 {
-    mPublisher->sessionsAdded(mPrx, sessions);
+    mPublisher->sessionsAdded(mPrx, sessions, cookies);
 }
 
-void BridgeListenerMgr::sessionsRemoved(const SessionSeq& sessions)
+void BridgeListenerMgr::sessionsRemoved(const SessionSeq& sessions, const BridgeCookies& cookies)
 {
-    mPublisher->sessionsRemoved(mPrx, sessions);
+    mPublisher->sessionsRemoved(mPrx, sessions, cookies);
 }
 
-void BridgeListenerMgr::stopped()
+void BridgeListenerMgr::stopped(const BridgeCookies& cookies)
 {
-    mPublisher->stopped(mPrx);
+    mPublisher->stopped(mPrx, cookies);
 }
 
-void BridgeListenerMgr::stopping()
+void BridgeListenerMgr::stopping(const BridgeCookies& cookies)
 {
-    mPublisher->stopping(mPrx);
+    mPublisher->stopping(mPrx, cookies);
 }
diff --git a/src/BridgeListenerMgr.h b/src/BridgeListenerMgr.h
index 5c31156..6bf07b1 100644
--- a/src/BridgeListenerMgr.h
+++ b/src/BridgeListenerMgr.h
@@ -30,10 +30,12 @@ public:
     BridgeListenerMgr(const Ice::CommunicatorPtr& communicator, const std::string& name,
         const AsteriskSCF::SessionCommunications::V1::BridgePrx& source);
 
-    void sessionsAdded(const AsteriskSCF::SessionCommunications::V1::SessionSeq& sessions);
-    void sessionsRemoved(const AsteriskSCF::SessionCommunications::V1::SessionSeq& sessions);
-    void stopped();
-    void stopping();
+    void sessionsAdded(const AsteriskSCF::SessionCommunications::V1::SessionSeq& sessions, 
+        const AsteriskSCF::SessionCommunications::V1::BridgeCookies& cookies);
+    void sessionsRemoved(const AsteriskSCF::SessionCommunications::V1::SessionSeq& sessions, 
+        const AsteriskSCF::SessionCommunications::V1::BridgeCookies& cookies);
+    void stopped(const AsteriskSCF::SessionCommunications::V1::BridgeCookies& cookies);
+    void stopping(const AsteriskSCF::SessionCommunications::V1::BridgeCookies& cookies);
 
 private:
     AsteriskSCF::SessionCommunications::V1::BridgePrx mPrx;
diff --git a/src/Service.cpp b/src/Service.cpp
index f0379d4..73aeb19 100644
--- a/src/Service.cpp
+++ b/src/Service.cpp
@@ -278,26 +278,27 @@ void BridgingApp::start(const std::string& name, const Ice::CommunicatorPtr& com
         manager->activate();
     }
 
-    if (!onStandby)
+    //
+    // This was only set if the service was not active, but I think this may change with the changes to the discovery params 
+    // and being able to specify ids.
+    //
+    bool registered = false;
+    try
     {
-        bool registered = false;
-        try
-        {
-            ServiceLocatorParamsPtr parameters(new ServiceLocatorParams);
-            parameters->category = BridgeServiceDiscoveryCategory;
-            mLocator = 
-                new LocatorRegistrationWrapper<BridgeManagerPrx>(communicator, serviceLocatorManagementProperty, bridgeManagerPrx, 
-                        adapterName, parameters);
-            registered = mLocator->registerService();
-        }
-        catch (const Ice::Exception&)
-        {
-        }
-        if (!registered)
-        {
-            mRegisterThread = new RegisterThread<BridgeManagerPrx>(mLocator);
-            mRegisterThread->start();
-        }
+        ServiceLocatorParamsPtr parameters(new ServiceLocatorParams);
+        parameters->category = BridgeServiceDiscoveryCategory;
+        mLocator = 
+            new LocatorRegistrationWrapper<BridgeManagerPrx>(communicator, serviceLocatorManagementProperty, bridgeManagerPrx, 
+                    adapterName, parameters);
+        registered = mLocator->registerService();
+    }
+    catch (const Ice::Exception&)
+    {
+    }
+    if (!registered)
+    {
+        mRegisterThread = new RegisterThread<BridgeManagerPrx>(mLocator);
+        mRegisterThread->start();
     }
     //
     // TODO: We need to know whether or not to activate!
diff --git a/test/BridgeListenerI.cpp b/test/BridgeListenerI.cpp
index 1499846..222995f 100644
--- a/test/BridgeListenerI.cpp
+++ b/test/BridgeListenerI.cpp
@@ -16,6 +16,7 @@
 #include "BridgeListenerI.h"
 
 using namespace AsteriskSCF::BridgingTest;
+using namespace std;
 
 BridgeListenerI::BridgeListenerI() :
     mShuttingDown(false),
@@ -23,27 +24,39 @@ BridgeListenerI::BridgeListenerI() :
 {
 }
 
-void BridgeListenerI::sessionsAdded(const AsteriskSCF::SessionCommunications::V1::BridgePrx&, const AsteriskSCF::SessionCommunications::V1::SessionSeq& sessions, const Ice::Current&)
+void BridgeListenerI::sessionsAdded(const AsteriskSCF::SessionCommunications::V1::BridgePrx&, 
+    const AsteriskSCF::SessionCommunications::V1::SessionSeq& sessions, 
+    const AsteriskSCF::SessionCommunications::V1::BridgeCookies& cookies, const Ice::Current&)
 {
+    updateCookieMap("sessionsAdded", cookies);
     IceUtil::Monitor<IceUtil::Mutex>::Lock lock(mAddMonitor);
-    mAdded.insert(mAdded.end(), sessions.begin(), sessions.end());
+    mAdded =sessions;
     mAddMonitor.notify();
 }
 
-void BridgeListenerI::sessionsRemoved(const AsteriskSCF::SessionCommunications::V1::BridgePrx&, const AsteriskSCF::SessionCommunications::V1::SessionSeq& sessions, const Ice::Current&)
+void BridgeListenerI::sessionsRemoved(const AsteriskSCF::SessionCommunications::V1::BridgePrx&, 
+    const AsteriskSCF::SessionCommunications::V1::SessionSeq& sessions, 
+    const AsteriskSCF::SessionCommunications::V1::BridgeCookies& cookies, const Ice::Current&)
 {
+    updateCookieMap("sessionsRemoved", cookies);
     IceUtil::Monitor<IceUtil::Mutex>::Lock lock(mRemoveMonitor);
-    mRemoved.insert(mRemoved.end(), sessions.begin(), sessions.end());
+    mRemoved = sessions;
     mRemoveMonitor.notify();
 }
 
-void BridgeListenerI::stopping(const AsteriskSCF::SessionCommunications::V1::BridgePrx&, const Ice::Current&)
+void BridgeListenerI::stopping(const AsteriskSCF::SessionCommunications::V1::BridgePrx&, 
+    const AsteriskSCF::SessionCommunications::V1::BridgeCookies& cookies, const Ice::Current&)
 {
+    updateCookieMap("stopping", cookies);
+    IceUtil::Monitor<IceUtil::Mutex>::Lock lock(mStateMonitor);
     mShuttingDown = true;
+    mStateMonitor.notify();
 }
 
-void BridgeListenerI::stopped(const AsteriskSCF::SessionCommunications::V1::BridgePrx&, const Ice::Current&)
+void BridgeListenerI::stopped(const AsteriskSCF::SessionCommunications::V1::BridgePrx&, 
+    const AsteriskSCF::SessionCommunications::V1::BridgeCookies& cookies, const Ice::Current&)
 {
+    updateCookieMap("stopped", cookies);
     IceUtil::Monitor<IceUtil::Mutex>::Lock lock(mStateMonitor);
     mStopped = true;
     mStateMonitor.notify();
@@ -53,6 +66,7 @@ bool BridgeListenerI::resetShuttingDown()
 {
     bool result = mShuttingDown;
     mShuttingDown = false;
+    mCookieMap.clear();
     return result;
 }
 
@@ -60,6 +74,7 @@ bool BridgeListenerI::resetStopped()
 {
     bool result = mStopped;
     mStopped = false;
+    mCookieMap.clear();
     return result;
 }
 
@@ -67,30 +82,26 @@ bool BridgeListenerI::waitForAdded(unsigned long milliseconds, AsteriskSCF::Sess
 {
     IceUtil::Monitor<IceUtil::Mutex>::Lock lock(mAddMonitor);
     bool waitResult = mAddMonitor.timedWait(IceUtil::Time::milliSeconds(milliseconds));
-    if(waitResult && mAdded.size() > 0)
-    {
-        added = mAdded;
-        return true;
-    }
-    return false;
+    added = mAdded;
+    mAdded.clear();
+    return !added.empty();
 }
 
 bool BridgeListenerI::waitForRemoved(unsigned long milliseconds, AsteriskSCF::SessionCommunications::V1::SessionSeq& removed)
 {
     IceUtil::Monitor<IceUtil::Mutex>::Lock lock(mRemoveMonitor);
     bool waitResult = mRemoveMonitor.timedWait(IceUtil::Time::milliSeconds(milliseconds));
-    if(waitResult && mRemoved.size() > 0)
-    {
-        removed = mRemoved;
-        return true;
-    }
-    return false;
+    removed = mRemoved;
+    mRemoved.clear();
+    return !removed.empty();
+
 }
 
 bool BridgeListenerI::waitForStopped(unsigned long milliseconds)
 {
     IceUtil::Monitor<IceUtil::Mutex>::Lock lock(mStateMonitor);
-    return mStateMonitor.timedWait(IceUtil::Time::milliSeconds(milliseconds));
+    mStateMonitor.timedWait(IceUtil::Time::milliSeconds(milliseconds));
+    return mStopped;
 }
 
 size_t BridgeListenerI::addedCount()
@@ -102,3 +113,16 @@ size_t BridgeListenerI::removedCount()
 {
     return mRemoved.size();
 }
+
+CookieMap BridgeListenerI::getCookieMap()
+{
+    IceUtil::Monitor<IceUtil::Mutex>::Lock lock(mCookieMapMonitor);
+    return mCookieMap;
+}
+
+void BridgeListenerI::updateCookieMap(const string& operation, 
+        const AsteriskSCF::SessionCommunications::V1::BridgeCookies& cookies)
+{
+    IceUtil::Monitor<IceUtil::Mutex>::Lock lock(mCookieMapMonitor);
+    mCookieMap[operation] = cookies;
+}
diff --git a/test/BridgeListenerI.h b/test/BridgeListenerI.h
index c8550e5..881de6b 100644
--- a/test/BridgeListenerI.h
+++ b/test/BridgeListenerI.h
@@ -16,20 +16,29 @@
 #pragma once
 
 #include <AsteriskSCF/SessionCommunications/SessionCommunicationsIf.h>
+#include <map>
+#include <string>
 
 namespace AsteriskSCF
 {
 namespace BridgingTest
 {
+typedef std::map<std::string, AsteriskSCF::SessionCommunications::V1::BridgeCookies> CookieMap;
 
 class BridgeListenerI : public AsteriskSCF::SessionCommunications::V1::BridgeListener
 {
 public:
     BridgeListenerI();
-    void sessionsAdded(const AsteriskSCF::SessionCommunications::V1::BridgePrx& bridge, const AsteriskSCF::SessionCommunications::V1::SessionSeq& sessions, const Ice::Current& current);
-    void sessionsRemoved(const AsteriskSCF::SessionCommunications::V1::BridgePrx& bridge, const AsteriskSCF::SessionCommunications::V1::SessionSeq& sessions, const Ice::Current& current);
-    void stopping(const AsteriskSCF::SessionCommunications::V1::BridgePrx& bridge, const Ice::Current& current);
-    void stopped(const AsteriskSCF::SessionCommunications::V1::BridgePrx& bridge, const Ice::Current& current);
+    void sessionsAdded(const AsteriskSCF::SessionCommunications::V1::BridgePrx& bridge, 
+        const AsteriskSCF::SessionCommunications::V1::SessionSeq& sessions, 
+        const AsteriskSCF::SessionCommunications::V1::BridgeCookies& cookies, const Ice::Current& current);
+    void sessionsRemoved(const AsteriskSCF::SessionCommunications::V1::BridgePrx& bridge, 
+        const AsteriskSCF::SessionCommunications::V1::SessionSeq& sessions, 
+        const AsteriskSCF::SessionCommunications::V1::BridgeCookies& cookies, const Ice::Current& current);
+    void stopping(const AsteriskSCF::SessionCommunications::V1::BridgePrx& bridge, 
+        const AsteriskSCF::SessionCommunications::V1::BridgeCookies& cookies, const Ice::Current& current);
+    void stopped(const AsteriskSCF::SessionCommunications::V1::BridgePrx& bridge, 
+        const AsteriskSCF::SessionCommunications::V1::BridgeCookies& cookies, const Ice::Current& current);
     bool resetShuttingDown();
     bool resetStopped();
 
@@ -40,6 +49,8 @@ public:
     size_t addedCount();
     size_t removedCount();
 
+    CookieMap getCookieMap();
+
 private:
     bool mShuttingDown;
     bool mStopped;
@@ -47,10 +58,17 @@ private:
     IceUtil::Monitor<IceUtil::Mutex> mAddMonitor;
     IceUtil::Monitor<IceUtil::Mutex> mRemoveMonitor;
     IceUtil::Monitor<IceUtil::Mutex> mStateMonitor;
+
+    IceUtil::Monitor<IceUtil::Mutex> mCookieMapMonitor;
+    CookieMap mCookieMap;
+
     AsteriskSCF::SessionCommunications::V1::SessionSeq mAdded;
     AsteriskSCF::SessionCommunications::V1::SessionSeq mRemoved;
     bool mSessionsAdded;
     bool mSessionsRemoved;
+
+    void updateCookieMap(const std::string& operation, 
+        const AsteriskSCF::SessionCommunications::V1::BridgeCookies& cookies);
 };
 
 typedef IceUtil::Handle<BridgeListenerI> BridgeListenerPtr;
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index a9de994..6f2f1af 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -6,7 +6,9 @@ include_directories(../src)
 astscf_slice_include_collection(TEST_CHANNEL)
 
 astscf_component_init(bridge_component_test)
+astscf_slice_collection(LOCAL PATH "${CMAKE_CURRENT_SOURCE_DIR}")
 astscf_component_add_slices(bridge_component_test TEST_CHANNEL AsteriskSCF/TestChannel/CommandsIf.ice)
+astscf_component_add_slices(bridge_component_test LOCAL TestCookieIf.ice)
 astscf_component_add_files(bridge_component_test TestBridging.cpp)
 astscf_component_add_files(bridge_component_test BridgeListenerI.h)
 astscf_component_add_files(bridge_component_test BridgeListenerI.cpp)
diff --git a/test/TestBridging.cpp b/test/TestBridging.cpp
index 82edf8d..38ecc55 100644
--- a/test/TestBridging.cpp
+++ b/test/TestBridging.cpp
@@ -28,6 +28,8 @@
 #include "TestCommandDriver.h"
 #include "../src/ServiceUtil.h"
 
+#include "TestCookieIf.h"
+
 #include <Ice/Ice.h>
 #include <IceBox/IceBox.h>
 
@@ -39,12 +41,108 @@ using namespace AsteriskSCF::BridgingTest;
 using namespace AsteriskSCF::SessionCommunications::V1;
 using namespace AsteriskSCF::Core::Discovery::V1;
 using namespace AsteriskSCF::Core::Routing::V1;
+using namespace AsteriskSCFTest;
 using namespace std;
 
 /* Cache the command line arguments so that Ice can be initialized within the global fixture. */
 namespace
 {
 
+BridgeCookies bakeTestCookies()
+{
+    BridgeCookies result;
+    TestCookieAPtr aCookie = new TestCookieA;
+    aCookie->astring = "I'm just a simple test cookie";
+    result.push_back(aCookie);
+
+    TestCookieBPtr bCookie = new TestCookieB;
+    bCookie->blong = 0xdeadbeef;
+    result.push_back(bCookie);
+
+    TestCookieDerivedFromBPtr derivedFromB = new TestCookieDerivedFromB;
+    derivedFromB->blong = 0xfeeffeef;
+    derivedFromB->bstring = "What the hex?";
+    result.push_back(derivedFromB);
+
+    TestNestedPtr nested1 = new TestNested;
+    nested1->baseString = "simple nested";
+
+    TestNestedDerivedPtr derivedNested= new TestNestedDerived;
+    derivedNested->baseString = "slightly less simple nested";
+    derivedNested->derivedLong = 42;
+
+    NestedTestSeq nestedObjs;
+    nestedObjs.push_back(nested1);
+    nestedObjs.push_back(derivedNested);
+    TestCookieCPtr cCookie = new TestCookieC;
+    cCookie->gettingALittleCrazyArentWe = nestedObjs;
+    result.push_back(cCookie);
+    return result;
+}
+
+void tasteCookies(const BridgeCookies& cookies, bool a, bool b, bool c, bool d)
+{
+    int count = 0;
+    if (a)
+    {
+        ++count;
+    }
+    if (b)
+    {
+        ++count;
+    }
+    if (c)
+    {
+        ++count;
+    }
+    if (d)
+    {
+        ++count;
+    }
+    BOOST_REQUIRE(cookies.size() == count);
+    for (BridgeCookies::const_iterator i = cookies.begin(); i != cookies.end(); ++i)
+    {
+        BridgeCookiePtr cookie = *i;
+        if (cookie->ice_id() == TestCookieA::ice_staticId())
+        {
+            a = !a;
+            BOOST_REQUIRE(TestCookieAPtr::dynamicCast(cookies[0])->astring == "I'm just a simple test cookie");
+        }
+        else if (cookie->ice_id() == TestCookieB::ice_staticId())
+        {
+            b = !b;
+            BOOST_REQUIRE(TestCookieBPtr::dynamicCast(cookies[1])->blong == 0xdeadbeef);
+        }
+        else if (cookie->ice_id() == TestCookieDerivedFromB::ice_staticId())
+        {
+            c = !c;
+            BOOST_REQUIRE(TestCookieDerivedFromBPtr::dynamicCast(cookie)->blong == 0xfeeffeef);
+            BOOST_REQUIRE(TestCookieDerivedFromBPtr::dynamicCast(cookie)->bstring == "What the hex?");
+        }
+        else if (cookie->ice_id() == TestCookieC::ice_staticId())
+        {
+            d = !d;
+            NestedTestSeq nestedObjs = TestCookieCPtr::dynamicCast(cookie)->gettingALittleCrazyArentWe;
+            BOOST_REQUIRE(nestedObjs.size() == 2);
+            BOOST_REQUIRE(nestedObjs[0]->ice_id() == TestNested::ice_staticId());
+            BOOST_REQUIRE(TestNestedPtr::dynamicCast(nestedObjs[0])->baseString == "simple nested");
+            BOOST_REQUIRE(nestedObjs[1]->ice_id() == TestNestedDerived::ice_staticId());
+            BOOST_REQUIRE(TestNestedDerivedPtr::dynamicCast(nestedObjs[1])->baseString == "slightly less simple nested");
+            BOOST_REQUIRE(TestNestedDerivedPtr::dynamicCast(nestedObjs[1])->derivedLong == 42);
+        }
+    }
+
+    BOOST_REQUIRE(!a);
+    BOOST_REQUIRE(!b);
+    BOOST_REQUIRE(!c);
+    BOOST_REQUIRE(!d);
+}
+
+void tasteCookies(const BridgeCookies& cookies)
+{
+    tasteCookies(cookies, true, true, true, true);
+}
+
 void propGetSet(const Ice::PropertiesPtr& p, const string& propertyName, const string& value)
 {
     p->setProperty(propertyName, p->getPropertyWithDefault(propertyName, value));
@@ -852,6 +950,208 @@ public:
         }
     }
 
+    //
+    // The following tests validate the operation of the bridge cookie API and the corresponding listener
+    // interface. The listener apis are evaluated for each method, but only once (for adding). After 
+    // that the getCookies is used to confirm the end result. We duplicate the tests that include replication
+    // to verify that replication of the cookies is occurring also.
+    //
+
+    void simpleCookieAddTest()
+    {
+        try
+        {
+            IceEnvironment testEnv(env()->properties());
+            try
+            {
+                Ice::ObjectAdapterPtr testAdapter =  testEnv.communicator()->createObjectAdapter("TestUtilAdapter");
+                testAdapter->activate();
+                BridgeManagerListenerIPtr servant = new BridgeManagerListenerI;
+                AsteriskSCF::SessionCommunications::V1::BridgeManagerListenerPrx listenerPrx;
+                addServant(listenerPrx, testAdapter, servant, testEnv.strToIdent(IceUtil::generateUUID()));
+
+                AsteriskSCF::SessionCommunications::V1::BridgeManagerPrx mgrPrx = env()->primaryBridgeManager();
+                BOOST_CHECK(mgrPrx);
+                mgrPrx->addListener(listenerPrx);
+                BOOST_CHECK(servant->stoppingCalls() == 0);
+                BOOST_CHECK(servant->stoppedCalls() == 0);
+                BOOST_CHECK(servant->createCalls() == 0);
+                AsteriskSCF::SessionCommunications::V1::SessionSeq sessions;
+                AsteriskSCF::SessionCommunications::V1::BridgePrx bridge(mgrPrx->createBridge(sessions, 0));
+                TestChannelWrapper channel(env()->properties());
+
+                AsteriskSCF::SessionCommunications::V1::SessionPrx a = channel.getSession("311");
+                AsteriskSCF::SessionCommunications::V1::SessionPrx b = channel.getSession("312");
+                sessions.push_back(a);
+                sessions.push_back(b);
+                //
+                // precondition checks for test validity.
+                //
+                std::string idA = testEnv.communicator()->identityToString(a->ice_getIdentity());
+                std::string idB = testEnv.communicator()->identityToString(b->ice_getIdentity());
+                std::vector<std::string> log;
+                channel.commands()->getlog(idA, log);
+                BOOST_CHECK(!find(log, "start"));
+                channel.commands()->getlog(idB, log);
+                BOOST_CHECK(!find(log, "start"));
+                BridgeCookies cookies = bakeTestCookies();
+                bridge->setCookies(cookies);
+                AsteriskSCF::BridgingTest::BridgeListenerPtr bridgeListener = new BridgeListenerI;
+                AsteriskSCF::SessionCommunications::V1::BridgeListenerPrx bridgeListenerPrx;
+                addServant(bridgeListenerPrx, testAdapter, bridgeListener, testEnv.strToIdent(IceUtil::generateUUID()));
+                bridge->addListener(bridgeListenerPrx);
+
+                AsteriskSCF::SessionCommunications::V1::SessionSeq eventSessions;
+                bridge->addSessions(sessions);
+                BOOST_REQUIRE(bridgeListener->waitForAdded(5000, eventSessions));
+                CookieMap cookieMap = bridgeListener->getCookieMap();
+                BOOST_REQUIRE(!cookieMap.empty());
+                BOOST_REQUIRE(!eventSessions.empty());
+
+                BOOST_REQUIRE(cookieMap.find("sessionsAdded") != cookieMap.end());
+                BridgeCookies returnedCookies = cookieMap["sessionsAdded"];
+                tasteCookies(returnedCookies);
+
+                sessions.clear();
+                sessions.push_back(b);
+                eventSessions.clear();
+                bridge->removeSessions(sessions);
+                BOOST_REQUIRE(bridgeListener->waitForRemoved(5000, eventSessions));
+                cookieMap = bridgeListener->getCookieMap();
+                BOOST_REQUIRE(!cookieMap.empty());
+                BOOST_REQUIRE(cookieMap.find("sessionsRemoved") != cookieMap.end());
+                returnedCookies = cookieMap["sessionsRemoved"];
+                tasteCookies(returnedCookies);
+
+                BOOST_REQUIRE(bridgeListener->waitForStopped(5000));
+                cookieMap = bridgeListener->getCookieMap();
+                BOOST_REQUIRE(cookieMap.find("stopping") != cookieMap.end());
+                returnedCookies = cookieMap["stopping"];
+                tasteCookies(returnedCookies);
+                BOOST_REQUIRE(cookieMap.find("stopped") != cookieMap.end());
+                returnedCookies = cookieMap["stopped"];
+                BOOST_REQUIRE(!returnedCookies.empty());
+                tasteCookies(returnedCookies);
+                returnedCookies = bridge->getCookies(cookies);
+                tasteCookies(returnedCookies);
+                
+            }
+            catch (const Ice::Exception& ex)
+            {
+                std::ostringstream msg;
+                msg << "Unexpected Ice exception " << ex.what();
+                BOOST_FAIL(msg.str());
+            }
+            catch (...)
+            {
+                BOOST_FAIL("Unexpected exception");
+            }
+        }
+        catch (...)
+        {
+            BOOST_FAIL("Unexpected exception");
+        }
+    }
+
+    void cookieAddRemoveTest()
+    {
+        try
+        {
+            IceEnvironment testEnv(env()->properties());
+            try
+            {
+                Ice::ObjectAdapterPtr testAdapter =  testEnv.communicator()->createObjectAdapter("TestUtilAdapter");
+                testAdapter->activate();
+                BridgeManagerListenerIPtr servant = new BridgeManagerListenerI;
+                AsteriskSCF::SessionCommunications::V1::BridgeManagerListenerPrx listenerPrx;
+                addServant(listenerPrx, testAdapter, servant, testEnv.strToIdent(IceUtil::generateUUID()));
+
+                AsteriskSCF::SessionCommunications::V1::BridgeManagerPrx mgrPrx = env()->primaryBridgeManager();
+                BOOST_CHECK(mgrPrx);
+                mgrPrx->addListener(listenerPrx);
+                BOOST_CHECK(servant->stoppingCalls() == 0);
+                BOOST_CHECK(servant->stoppedCalls() == 0);
+                BOOST_CHECK(servant->createCalls() == 0);
+                AsteriskSCF::SessionCommunications::V1::SessionSeq sessions;
+                AsteriskSCF::SessionCommunications::V1::BridgePrx bridge(mgrPrx->createBridge(sessions, 0));
+                TestChannelWrapper channel(env()->properties());
+
+                AsteriskSCF::SessionCommunications::V1::SessionPrx a = channel.getSession("311");
+                AsteriskSCF::SessionCommunications::V1::SessionPrx b = channel.getSession("312");
+                sessions.push_back(a);
+                sessions.push_back(b);
+                //
+                // precondition checks for test validity.
+                //
+                std::string idA = testEnv.communicator()->identityToString(a->ice_getIdentity());
+                std::string idB = testEnv.communicator()->identityToString(b->ice_getIdentity());
+                std::vector<std::string> log;
+                channel.commands()->getlog(idA, log);
+                BOOST_CHECK(!find(log, "start"));
+                channel.commands()->getlog(idB, log);
+                BOOST_CHECK(!find(log, "start"));
+                BridgeCookies cookies = bakeTestCookies();
+                bridge->setCookies(cookies);
+                AsteriskSCF::BridgingTest::BridgeListenerPtr bridgeListener = new BridgeListenerI;
+                AsteriskSCF::SessionCommunications::V1::BridgeListenerPrx bridgeListenerPrx;
+                addServant(bridgeListenerPrx, testAdapter, bridgeListener, testEnv.strToIdent(IceUtil::generateUUID()));
+                bridge->addListener(bridgeListenerPrx);
+
+                AsteriskSCF::SessionCommunications::V1::SessionSeq eventSessions;
+                bridge->addSessions(sessions);
+                BOOST_REQUIRE(bridgeListener->waitForAdded(5000, eventSessions));
+                CookieMap cookieMap = bridgeListener->getCookieMap();
+                BOOST_REQUIRE(!cookieMap.empty());
+                BOOST_REQUIRE(!eventSessions.empty());
+
+                BOOST_REQUIRE(cookieMap.find("sessionsAdded") != cookieMap.end());
+                BridgeCookies returnedCookies = cookieMap["sessionsAdded"];
+                tasteCookies(returnedCookies);
+                BridgeCookies toRemove;
+                toRemove.push_back(cookies[1]);
+                bridge->removeCookies(toRemove);
+
+                sessions.clear();
+                sessions.push_back(b);
+                eventSessions.clear();
+                bridge->removeSessions(sessions);
+                BOOST_REQUIRE(bridgeListener->waitForRemoved(5000, eventSessions));
+                cookieMap = bridgeListener->getCookieMap();
+                BOOST_REQUIRE(!cookieMap.empty());
+                BOOST_REQUIRE(cookieMap.find("sessionsRemoved") != cookieMap.end());
+                returnedCookies = cookieMap["sessionsRemoved"];
+                tasteCookies(returnedCookies, true, false, true, true);
+
+                BOOST_REQUIRE(bridgeListener->waitForStopped(5000));
+                cookieMap = bridgeListener->getCookieMap();
+                BOOST_REQUIRE(cookieMap.find("stopping") != cookieMap.end());
+                returnedCookies = cookieMap["stopping"];
+                tasteCookies(returnedCookies, true, false, true, true);
+                BOOST_REQUIRE(cookieMap.find("stopped") != cookieMap.end());
+                returnedCookies = cookieMap["stopped"];
+                BOOST_REQUIRE(!returnedCookies.empty());
+                tasteCookies(returnedCookies, true, false, true, true);
+                cookies.erase(cookies.begin() +1); 
+                returnedCookies = bridge->getCookies(cookies);
+                tasteCookies(returnedCookies, true, false, true, true);
+            }
+            catch (const Ice::Exception& ex)
+            {
+                std::ostringstream msg;
+                msg << "Unexpected Ice exception " << ex.what();
+                BOOST_FAIL(msg.str());
+            }
+            catch (...)
+            {
+                BOOST_FAIL("Unexpected exception");
+            }
+        }
+        catch (...)
+        {
+            BOOST_FAIL("Unexpected exception");
+        }
+    }
+
 private:
     TestEnvironmentPtr mTestEnvironment;
 };
@@ -875,6 +1175,10 @@ bool init_unit_test()
         add(BOOST_TEST_CASE(boost::bind(&BridgeTester::testReplaceSession, bridgeTester)));
     framework::master_test_suite().
         add(BOOST_TEST_CASE(boost::bind(&BridgeTester::testBridgeManagerListenerReplication, bridgeTester)));
+    framework::master_test_suite().
+        add(BOOST_TEST_CASE(boost::bind(&BridgeTester::simpleCookieAddTest, bridgeTester)));
+    framework::master_test_suite().
+        add(BOOST_TEST_CASE(boost::bind(&BridgeTester::cookieAddRemoveTest, bridgeTester)));
     return true;
 }
 
diff --git a/test/TestCookieIf.ice b/test/TestCookieIf.ice
new file mode 100644
index 0000000..dbd46ad
--- /dev/null
+++ b/test/TestCookieIf.ice
@@ -0,0 +1,54 @@
+/*
+ * 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 <AsteriskSCF/SessionCommunications/SessionCommunicationsIf.ice>
+
+module AsteriskSCFTest
+{
+unsliceable class TestCookieA extends AsteriskSCF::SessionCommunications::V1::BridgeCookie
+{
+    string astring;
+};
+
+unsliceable class TestCookieB extends AsteriskSCF::SessionCommunications::V1::BridgeCookie
+{
+    long blong;
+};
+
+unsliceable class TestCookieDerivedFromB extends TestCookieB
+{
+    string bstring;
+};
+
+unsliceable class TestNested
+{
+    string baseString;
+};
+
+unsliceable class TestNestedDerived extends TestNested
+{
+    long derivedLong;
+};
+
+sequence<TestNested> NestedTestSeq;
+
+unsliceable class TestCookieC extends AsteriskSCF::SessionCommunications::V1::BridgeCookie
+{
+    NestedTestSeq gettingALittleCrazyArentWe;
+};
+
+}; /* End of module AsteriskSCFTest */

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


-- 
asterisk-scf/integration/bridging.git



More information about the asterisk-scf-commits mailing list