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

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Thu Oct 6 06:58:09 CDT 2011


branch "mediamixer" has been updated
       via  2f1624d27cf6613124b67af667ce0165c9283331 (commit)
       via  1e99ad99de150e86169a828a6341717dad05e110 (commit)
       via  7d67896288e9087ba634e48430f0417f3e3e1526 (commit)
       via  bf4b6cc530ddcf99d7177913073b97433cb3b5d5 (commit)
       via  19496522bf61f9a2805b5e7fc895909634b9a50e (commit)
       via  649687f8e6d0723c82155cf25b7f2fbe014b6517 (commit)
       via  2791d5926944131ea67ddd03ea9011632d47803a (commit)
       via  c43e634f98fd7daaabbf30877763b005f914b2b9 (commit)
       via  843fe4b41b446f7f42361bfb9fbf2ff0e1143a66 (commit)
       via  66d6f56ab231036d1bd84c8b057473b884159eeb (commit)
       via  7af97676c33ca5f32dbcf924bd02c2b31c230d4a (commit)
       via  7ae703dcaf863f700b577ec6796e3ef81bbb0ebf (commit)
      from  fceeb4bfdd74b62e09da30446aaf2e2f90608a9a (commit)

Summary of changes:
 config/bridging.conf                               |   13 +-
 config/test_bridging.conf                          |  119 +---
 .../BridgeService/BridgeReplicatorIf.ice           |   29 +-
 src/BridgeCreationExtensionPointImpl.cpp           |  141 +++++
 src/BridgeCreationExtensionPointImpl.h             |   54 ++
 src/BridgeImpl.cpp                                 |  634 ++++++++++++++++++--
 src/BridgeImpl.h                                   |   11 +-
 src/BridgeManagerImpl.cpp                          |  259 +++++++--
 src/BridgeManagerImpl.h                            |   11 +-
 src/BridgeManagerListenerMgr.h                     |    1 +
 src/BridgePartyIdExtensionPoint.cpp                |  175 ++++++
 src/BridgePartyIdExtensionPoint.h                  |   82 +++
 src/BridgeReplicationContext.h                     |   39 +-
 src/BridgeReplicatorService.cpp                    |    7 +-
 src/BridgeReplicatorStateListenerI.cpp             |    4 +-
 src/CMakeLists.txt                                 |    4 +
 src/Component.cpp                                  |   83 ++-
 src/MediaMixer.cpp                                 |   22 +-
 src/MediaSplicer.cpp                               |   23 +-
 src/SessionCollection.cpp                          |    2 +-
 src/SessionListener.cpp                            |    4 +-
 src/SessionOperations.cpp                          |  114 ++++-
 src/SessionOperations.h                            |   42 ++-
 src/SessionWrapper.cpp                             |   58 ++-
 src/SessionWrapper.h                               |   15 +
 src/Tasks.h                                        |   16 +-
 test/BridgeListenerI.cpp                           |   19 +-
 test/BridgeListenerI.h                             |    5 +-
 test/CMakeLists.txt                                |    2 +-
 test/TestBridging.cpp                              |  268 ++++++++-
 30 files changed, 1957 insertions(+), 299 deletions(-)
 create mode 100755 src/BridgeCreationExtensionPointImpl.cpp
 create mode 100755 src/BridgeCreationExtensionPointImpl.h
 create mode 100644 src/BridgePartyIdExtensionPoint.cpp
 create mode 100644 src/BridgePartyIdExtensionPoint.h


- Log -----------------------------------------------------------------
commit 2f1624d27cf6613124b67af667ce0165c9283331
Merge: fceeb4b 1e99ad9
Author: Joshua Colp <jcolp at digium.com>
Date:   Thu Oct 6 08:58:10 2011 -0300

    Merge branch 'master' into mediamixer
    
    Conflicts:
    	src/BridgeImpl.cpp
    	src/MediaSplicer.cpp
    	src/SessionOperations.cpp
    	src/SessionOperations.h
    	src/SessionWrapper.h
    	test/CMakeLists.txt

diff --cc src/MediaMixer.cpp
index 77df38d,0000000..7c92704
mode 100755,000000..100755
--- a/src/MediaMixer.cpp
+++ b/src/MediaMixer.cpp
@@@ -1,525 -1,0 +1,539 @@@
 +/*
 + * Asterisk SCF -- An open-source communications framework.
 + *
 + * Copyright (C) 2010-2011, Digium, Inc.
 + *
 + * See http://www.asterisk.org for more information about
 + * the Asterisk SCF project. Please do not directly contact
 + * any of the maintainers of this project for assistance;
 + * the project provides a web site, mailing lists and IRC
 + * channels for your use.
 + *
 + * This program is free software, distributed under the terms of
 + * the GNU General Public License Version 2. See the LICENSE.txt file
 + * at the top of the source tree.
 + */
 +#include "MediaMixer.h"
 +#include <Ice/Ice.h>
 +#include <IceUtil/Shared.h>
 +#include <IceUtil/Handle.h>
 +
 +using namespace AsteriskSCF::System::Logging;
 +using namespace AsteriskSCF::Media::V1;
 +using namespace std;
 +
 +namespace AsteriskSCF
 +{
 +namespace BridgeService
 +{
 +
 +/**
 + * Interval (in milliseconds) that media is mixed in.
 + */
 +#define MIXING_INTERVAL 20
 +
 +/**
 + * Implementation of a StreamSource which provides mixed audio.
 + */
 +class MediaMixerSource : public StreamSource
 +{
 +public:
 +    MediaMixerSource(const MediaMixerPtr& mixer) : mMixer(mixer) { }
 +
 +    void addSink(const StreamSinkPrx& sink, const Ice::Current&)
 +    {
 +        boost::unique_lock<boost::shared_mutex> lock(mLock);
 +
 +        if (std::find(mSinks.begin(), mSinks.end(), sink) != mSinks.end())
 +        {
 +            return;
 +        }
 +
 +        mSinks.push_back(sink);
 +    }
 +
 +    void removeSink(const StreamSinkPrx& sink, const Ice::Current&)
 +    {
 +        boost::unique_lock<boost::shared_mutex> lock(mLock);
 +
 +        mSinks.erase(std::remove(mSinks.begin(), mSinks.end(), sink), mSinks.end());
 +
 +        // If no more sinks exist then this should terminate
 +        if (mSinks.empty())
 +        {
 +            mMixer->removeSource(this, mProxy);
 +        }
 +    }
 +    
 +    StreamSinkSeq getSinks(const Ice::Current&)
 +    {
 +        boost::shared_lock<boost::shared_mutex> lock(mLock);
 +
 +        return mSinks;
 +    }
 +    
 +    FormatSeq getFormats(const Ice::Current&)
 +    {
 +        // This is not protected by the lock because once created this will never be altered
 +        return mFormats;
 +    }
 +    
 +    std::string getId(const Ice::Current&)
 +    {
 +        // Same goes for the id
 +        return mProxy->ice_getIdentity().name;
 +    }
 +    
 +    void requestFormat(const AsteriskSCF::Media::V1::FormatPtr&, const Ice::Current&)
 +    {
 +        throw MediaFormatSwitchException();
 +    }
 +
 +    /**
 +     * Internal function which sets our proxy.
 +     */
 +    void setProxy(const StreamSourcePrx& proxy)
 +    {
 +        mProxy = proxy;
 +    }
 +
 +    /**
 +     * Internal function which gets our proxy.
 +     */
 +    StreamSourcePrx getProxy()
 +    {
 +        return mProxy;
 +    }
 +
 +private:
 +    /**
 +     * Lock which protects this source.
 +     */
 +    boost::shared_mutex mLock;
 +
 +    /**
 +     * Media mixer we are associated with.
 +     */
 +    MediaMixerPtr mMixer;
 +
 +    /**
 +     * Proxy to ourselves.
 +     */
 +    StreamSourcePrx mProxy;
 +
 +    /**
 +     * Sinks that we are writing media to.
 +     */
 +    StreamSinkSeq mSinks;
 +
 +    /**
 +     * Formats supported by this source.
 +     */
 +    FormatSeq mFormats;
 +};
 +
 +/**
 + * Implementation of a StreamSink which provides audio to be mixed into the bridge.
 + */
 +class MediaMixerSink : public StreamSink
 +{
 +public:
 +    MediaMixerSink(const MediaMixerPtr& mixer, const MediaMixerSourcePtr& source) :
 +        mMixer(mixer), mLocalSource(source) { }
 +
 +    void write(const FrameSeq& frames, const Ice::Current&)
 +    {
 +        boost::unique_lock<boost::shared_mutex> lock(mLock);
 +
 +        mFrames.insert(mFrames.begin(), frames.begin(), frames.end());
 +    }
 +    
 +    void setSource(const StreamSourcePrx& source, const Ice::Current&)
 +    {
 +        boost::unique_lock<boost::shared_mutex> lock(mLock);
 +
 +        if (source == 0)
 +        {
 +            mMixer->removeSink(this, mProxy);
 +        }
 +        else
 +        {
 +            mSource = source;
 +        }
 +    }
 +    
 +    StreamSourcePrx getSource(const Ice::Current&)
 +    {
 +        boost::shared_lock<boost::shared_mutex> lock(mLock);
 +
 +        return mSource;
 +    }
 +    
 +    FormatSeq getFormats(const Ice::Current&)
 +    {
 +        return mFormats;
 +    }
 +    
 +    std::string getId(const Ice::Current&)
 +    {
 +        return mProxy->ice_getIdentity().name;
 +    }
 +
 +    /**
 +     * Internal function which returns the latest frame to use in the mixer.
 +     */
 +    const FramePtr& getFrame()
 +    {
 +        boost::unique_lock<boost::shared_mutex> lock(mLock);
 +
 +        if (!mFrames.empty())
 +        {
 +            mProvidedFrame = mFrames.back();
 +            mFrames.pop_back();
 +        }
 +
 +        return mProvidedFrame;
 +    }
 +
 +    /**
 +     * Internal function which removes the latest frame, presumably having already been mixed.
 +     */
 +    const FramePtr popFrame()
 +    {
 +        boost::unique_lock<boost::shared_mutex> lock(mLock);
 +
 +        FramePtr frame = mProvidedFrame;
 +        mProvidedFrame = 0;
 +
 +        return frame;
 +    }
 +
 +    /**
 +     * Internal function which sets our proxy.
 +     */
 +    void setProxy(const StreamSinkPrx& proxy)
 +    {
 +        mProxy = proxy;
 +    }
 +
 +    /**
 +     * Internal function which returns our proxy.
 +     */
 +    StreamSinkPrx getProxy()
 +    {
 +        return mProxy;
 +    }
 +
 +    /**
 +     * Internal function which returns the local source.
 +     */
 +    MediaMixerSourcePtr getLocalSource()
 +    {
 +        return mLocalSource;
 +    }
 +
 +private:
 +    /**
 +     * Lock which protects this sink.
 +     */
 +    boost::shared_mutex mLock;
 +
 +    /**
 +     * Media mixer we are associated with.
 +     */
 +    MediaMixerPtr mMixer;
 +
 +    /**
 +     * Pointer to our source of media, this exists within this class because the two
 +     * are inherently associated.
 +     */
 +    MediaMixerSourcePtr mLocalSource;
 +
 +    /**
 +     * Proxy to ourselves.
 +     */
 +    StreamSinkPrx mProxy;
 +
 +    /**
 +     * Sequence of received frames pending mixing.
 +     */
 +    FrameSeq mFrames;
 +
 +    /**
 +     * Source of media for this sink.
 +     */
 +    StreamSourcePrx mSource;
 +
 +    /**
 +     * Formats supported by this sink.
 +     */
 +    FormatSeq mFormats;
 +
 +    /**
 +     * Frame we provided when getFrame was called.
 +     */
 +    FramePtr mProvidedFrame;
 +};
 +
 +/**
 + * Simple callback object used when writing to sinks.
 + */
 +class WriteCallback : public IceUtil::Shared
 +{
 +public:
 +    void writtenCB()
 +    {
 +    }
 +
 +    void failureCB(const Ice::Exception&)
 +    {
 +    }
 +};
 +
 +/**
 + * Smart pointer for the above WriteCallback class.
 + */
 +typedef IceUtil::Handle<WriteCallback> WriteCallbackPtr;
 +
 +class MediaMixerI
 +{
 +public:
 +    MediaMixerI(const Ice::ObjectAdapterPtr& adapter) : mAdapter(adapter), mTimer(new IceUtil::Timer()),
 +                                                        mCallback(new WriteCallback()) { }
 +
 +    /**
 +     * Lock which protects the mixer.
 +     */
 +    boost::shared_mutex mLock;
 +
 +    /**
 +     * Object adapter that sinks/sources are on.
 +     */
 +    Ice::ObjectAdapterPtr mAdapter;
 +
 +    /**
 +     * Vector of sinks for media.
 +     */
 +    std::vector<MediaMixerSinkPtr> mSinks;
 +
 +    /**
 +     * Vector of sources for media.
 +     */
 +    std::vector<MediaMixerSourcePtr> mSources;
 +
 +    /**
 +     * Timer thread used to mix the media.
 +     */
 +    IceUtil::TimerPtr mTimer;
 +
 +    /**
 +     * Callback object for when writing to sinks.
 +     */
 +    WriteCallbackPtr mCallback;
 +};
 +
 +/**
 + * Transform function which performs a signed linear saturated add.
 + */
 +static short saturatedSignedLinearAdd(short input, short value)
 +{
 +    int res = input + value;
 +
 +    if (res > 32767)
 +    {
 +        return 32767;
 +    }
 +    else if (res < -32767)
 +    {
 +        return -32767;
 +    }
 +    else
 +    {
 +        return static_cast<short>(res);
 +    }
 +}
 +
 +/**
 + * Transform function which performs a signed linear saturated subtract.
 + */
 +static short saturatedSignedLinearSubtract(short input, short value)
 +{
 +    int res = input - value;
 +
 +    if (res > 32767)
 +    {
 +        return 32767;
 +    }
 +    else if (res < -32767)
 +    {
 +        return -32767;
 +    }
 +    else
 +    {
 +        return static_cast<short>(res);
 +    }
 +}
 +
 +MediaMixer::MediaMixer(const Ice::ObjectAdapterPtr& adapter) : mImpl(new MediaMixerI(adapter))
 +{
 +    mImpl->mTimer->scheduleRepeated(this, IceUtil::Time::milliSeconds(MIXING_INTERVAL));
 +}
 +
 +void MediaMixer::createMixing(const Ice::Identity& sinkId, AsteriskSCF::Media::V1::StreamSinkPrx& mixerSink,
 +                              const Ice::Identity& sourceId, AsteriskSCF::Media::V1::StreamSourcePrx& mixerSource)
 +{
 +    boost::unique_lock<boost::shared_mutex> lock(mImpl->mLock);
 +
 +    // The source is where mixed audio will originate from, within this implementation it essentially acts
 +    // as a store of sinks we need to write to for this source
 +    Ice::Identity id = sourceId;
 +    id.name += ".mixer";
 +    MediaMixerSourcePtr source;
 +    if (mImpl->mAdapter->find(id))
 +    {
 +        mixerSource = StreamSourcePrx::uncheckedCast(mImpl->mAdapter->createProxy(id));
 +    }
 +    else
 +    {
 +        source = new MediaMixerSource(this);
 +        mImpl->mSources.push_back(source);
 +        mixerSource = StreamSourcePrx::uncheckedCast(mImpl->mAdapter->add(source, id));
 +        source->setProxy(mixerSource);
 +    }
 +
 +    // The sink is where the source will send audio to to be mixed into the bridge, the reason the local source
 +    // is associated is because we need to know what media to remove from the mixed frame when writing out
 +    id = sinkId;
 +    id.name += ".mixer";
 +    if (mImpl->mAdapter->find(id))
 +    {
 +        mixerSink = StreamSinkPrx::uncheckedCast(mImpl->mAdapter->createProxy(id));
 +    }
 +    else
 +    {
 +        MediaMixerSinkPtr sink = new MediaMixerSink(this, source);
 +        mImpl->mSinks.push_back(sink);
 +        mixerSink = StreamSinkPrx::uncheckedCast(mImpl->mAdapter->add(sink, id));
 +        sink->setProxy(mixerSink);
 +    }
 +}
 +
 +void MediaMixer::runTimerTask()
 +{
 +    std::vector<MediaMixerSinkPtr> sinks;
 +
 +    {
 +        boost::shared_lock<boost::shared_mutex> lock(mImpl->mLock);
 +        sinks = mImpl->mSinks;
 +    }
 +
 +    FramePtr frame = new Frame();
 +
++    ByteSeqPayloadPtr mixedPayload = new ByteSeqPayload();
++    frame->payload = mixedPayload;
++
 +    for (std::vector<MediaMixerSinkPtr>::const_iterator sink = sinks.begin();
 +         sink != sinks.end();
 +         ++sink)
 +    {
 +        FramePtr sinkFrame = (*sink)->getFrame();
 +
 +        // If no frame exists for us to mix in skip doing so
 +        if (!sinkFrame)
 +        {
 +            continue;
 +        }
 +
-         std::transform(frame->payload.begin(), frame->payload.end(),
-                        sinkFrame->payload.begin(), sinkFrame->payload.end(),
++        ByteSeqPayloadPtr payload = ByteSeqPayloadPtr::dynamicCast(sinkFrame->payload);
++
++        // We only currently support byte sequence payloads
++        if (!payload)
++        {
++            continue;
++        }
++
++        std::transform(mixedPayload->payload.begin(), mixedPayload->payload.end(),
++                       payload->payload.begin(), payload->payload.end(),
 +                       saturatedSignedLinearAdd);
 +    }
 +
 +    for (std::vector<MediaMixerSinkPtr>::const_iterator sink = sinks.begin();
 +         sink != sinks.end();
 +         ++sink)
 +    {
 +        FramePtr sinkFrame = (*sink)->popFrame();
 +	FramePtr theirFrame(frame);
 +
 +        if (sinkFrame)
 +        {
 +            // If a frame was mixed in mix it out so we don't send their own audio to them
 +	    theirFrame = FramePtr::dynamicCast(frame->ice_clone());
 +
-             std::transform(theirFrame->payload.begin(), theirFrame->payload.end(),
-                            sinkFrame->payload.begin(), sinkFrame->payload.end(),
++            ByteSeqPayloadPtr sinkPayload = ByteSeqPayloadPtr::dynamicCast(sinkFrame->payload);
++            ByteSeqPayloadPtr payload = ByteSeqPayloadPtr::dynamicCast(theirFrame->payload);
++
++            std::transform(payload->payload.begin(), payload->payload.end(),
++                           sinkPayload->payload.begin(), sinkPayload->payload.end(),
 +                           saturatedSignedLinearSubtract);
 +        }
 +
 +        // Send this frame to all the sinks we should
 +        StreamSinkSeq sourceSinks = (*sink)->getLocalSource()->getSinks(Ice::Current());
 +
 +	FrameSeq frames;
 +	frames.push_back(theirFrame);
 +
 +        for (StreamSinkSeq::const_iterator sourceSink = sourceSinks.begin();
 +             sourceSink != sourceSinks.end();
 +             ++sourceSink)
 +        {
 +            (*sourceSink)->begin_write(frames, newCallback_StreamSink_write(mImpl->mCallback,
 +                                                                            &WriteCallback::writtenCB,
 +                                                                            &WriteCallback::failureCB));
 +        }
 +    }
 +}
 +
 +void MediaMixer::removeSource(const MediaMixerSourcePtr& source, const StreamSourcePrx& proxy)
 +{
 +    boost::unique_lock<boost::shared_mutex> lock(mImpl->mLock);
 +
 +    mImpl->mSources.erase(std::remove(mImpl->mSources.begin(), mImpl->mSources.end(), source), mImpl->mSources.end());
 +    mImpl->mAdapter->remove(proxy->ice_getIdentity());
 +}
 +
 +void MediaMixer::removeSink(const MediaMixerSinkPtr& sink, const StreamSinkPrx& proxy)
 +{
 +    boost::unique_lock<boost::shared_mutex> lock(mImpl->mLock);
 +
 +    mImpl->mSinks.erase(std::remove(mImpl->mSinks.begin(), mImpl->mSinks.end(), sink), mImpl->mSinks.end());
 +    mImpl->mAdapter->remove(proxy->ice_getIdentity());
 +}
 +
 +void MediaMixer::stop()
 +{
 +    boost::unique_lock<boost::shared_mutex> lock(mImpl->mLock);
 +
 +    mImpl->mTimer->destroy();
 +
 +    for (std::vector<MediaMixerSinkPtr>::const_iterator sink = mImpl->mSinks.begin();
 +         sink != mImpl->mSinks.end();
 +         ++sink)
 +    {
 +        mImpl->mAdapter->remove((*sink)->getProxy()->ice_getIdentity());
 +    }
 +
 +    mImpl->mSinks.clear();
 +
 +    for (std::vector<MediaMixerSourcePtr>::const_iterator source = mImpl->mSources.begin();
 +         source != mImpl->mSources.end();
 +         ++source)
 +    {
 +        mImpl->mAdapter->remove((*source)->getProxy()->ice_getIdentity());
 +    }
 +
 +    mImpl->mSources.clear();
 +}
 +
 +}
 +}
diff --cc src/MediaSplicer.cpp
index cfebdb3,8022a66..d9a7cef
--- a/src/MediaSplicer.cpp
+++ b/src/MediaSplicer.cpp
@@@ -793,21 -686,8 +793,22 @@@ public
  protected:
      bool executeImpl()
      {
 -	mSplicer->findCompatiblePairings(mMaterials->streams, mMaterials->outgoingPairings, mMaterials->incomingPairings,
 -                                         mMaterials->connector, mMaterials->connections, mMaterials->directConnections);
++
 +        if (mMaterials->streams.empty())
 +        {
 +            return true;
 +        }
 +
 +        if (mMixer == true)
 +        {
 +            mSplicer->findCompatiblePairings(mMaterials->streams, mMaterials->outgoingPairings, mMaterials->incomingPairings);
 +        }
 +        else
 +        {
 +            mSplicer->findCompatiblePairings(mMaterials->streams, mMaterials->outgoingPairings, mMaterials->incomingPairings,
 +                                             mMaterials->connector, mMaterials->connections, mMaterials->directConnections);
 +        }
 +
          return true;
      }
  
diff --cc src/SessionOperations.cpp
index 00d3e70,38c0184..df4b8ae
--- a/src/SessionOperations.cpp
+++ b/src/SessionOperations.cpp
@@@ -229,3 -233,106 +233,107 @@@ void RemoveStreamsOperation::removed(co
  void RemoveStreamsOperation::failed(const Ice::Exception&, const SessionWrapperPtr&)
  {
  }
+ 
+ ConnectTelephonyOperation::ConnectTelephonyOperation(const TelephonySessionPrx& sessionToConnect,
+                                                      const vector<TelephonySessionPrx>& ignoreList,
+                                                      const Logger& logger)
+                                                        : mSessionToConnect(sessionToConnect),
+                                                          mIgnoreList(ignoreList),
+                                                          mLogger(logger)
+ {
+ }
+ 
+ void ConnectTelephonyOperation::operator()(const SessionWrapperPtr& session)
+ {
+     if (session->getSession()->ice_getIdentity() == mSessionToConnect->ice_getIdentity())
+     {
+         // Let's not connect a session to itself. . 
+         return;
+     }
+ 
+     TelephonySessionPrx visitedTelephonySession = TelephonySessionPrx::checkedCast(session->getSession());
+     if (visitedTelephonySession == 0)
+     {
+         // If the session being visited isn't telephony, nothing to do. 
+         return;
+     }
+ 
+     if (inIgnoreList(visitedTelephonySession))
+     {
+         return;
+     }
+ 
+     connectSinks(mSessionToConnect, visitedTelephonySession);
+     connectSinks(visitedTelephonySession, mSessionToConnect);
+ 
+ }
+ 
+ bool ConnectTelephonyOperation::inIgnoreList(const TelephonySessionPrx& session)
+ {
+     for(vector<TelephonySessionPrx>::iterator i=mIgnoreList.begin();   
+         i != mIgnoreList.end(); ++i)
+     {
+         if (session->ice_getIdentity() == (*i)->ice_getIdentity())
+         {
+             return true;
+         }
+     }
+ 
+     return false;
+ }
+ 
+ void ConnectTelephonyOperation::connectSinks
+     (const TelephonySessionPrx& sourceSession, 
+      const TelephonySessionPrx& sinkSession)
+ {
+     TelephonyEventSinkSeq sinksToAdd = sinkSession->getSinks();
+     TelephonyEventSourceSeq toSources = sourceSession->getSources();
+ 
+     for(TelephonyEventSourceSeq::iterator i=toSources.begin();   
+         i != toSources.end(); ++i)
+     {
+             (*i)->addSinks(sinksToAdd);
+     }
+ }
+ 
+ DisconnectTelephonyOperation::DisconnectTelephonyOperation(const TelephonySessionPrx& sessionToDisconnect,
+                                                            const Logger& logger)
+                                                        : mSessionToDisconnect(sessionToDisconnect),
+                                                          mLogger(logger)
+ {
+ }
+ 
+ void DisconnectTelephonyOperation::operator()(const SessionWrapperPtr& visitedSession)
+ {
+     if (visitedSession->getSession()->ice_getIdentity() == mSessionToDisconnect->ice_getIdentity())
+     {
+         // Not connected to ourselves.
+         return;
+     }
+ 
+     TelephonySessionPrx visitedTelephonySession = TelephonySessionPrx::checkedCast(visitedSession->getSession());
+     if (visitedTelephonySession == 0)
+     {
+         // If the session being visited isn't telephony, nothing to do. 
+         return;
+     }
+ 
+     disconnectSinks(mSessionToDisconnect, visitedTelephonySession);
+     disconnectSinks(visitedTelephonySession, mSessionToDisconnect);
+ 
+ }
+ 
+ void DisconnectTelephonyOperation::disconnectSinks
+     (const TelephonySessionPrx& sourceSession, 
+      const TelephonySessionPrx& sinkSession)
+ {
+     TelephonyEventSinkSeq sinksToRemove = sinkSession->getSinks();
+     TelephonyEventSourceSeq fromSources = sourceSession->getSources();
+ 
+     for(TelephonyEventSourceSeq::iterator i=fromSources.begin();   
+         i != fromSources.end(); ++i)
+     {
+             (*i)->removeSinks(sinksToRemove);
+     }
+ }
++
diff --cc src/SessionWrapper.cpp
index 45aebf5,4adbd59..11b59b8
--- a/src/SessionWrapper.cpp
+++ b/src/SessionWrapper.cpp
@@@ -504,11 -506,8 +506,11 @@@ void SessionWrapper::setConnector(cons
  
  void SessionWrapper::updateMedia(const SessionPairingPtr& pairings)
  {
-     mLogger(Debug) << FUNLOG << " for " << mId;
+     mLogger(Trace) << FUNLOG << " for " << mId;
      boost::unique_lock<boost::shared_mutex> lock(mLock);
 +
 +    mSplicer->update(pairings);
 +
      if (mConnector)
      {
          mConnector->update(pairings);
diff --cc src/SessionWrapper.h
index 0bdef83,6fc3f43..a03d78b
--- a/src/SessionWrapper.h
+++ b/src/SessionWrapper.h
@@@ -157,6 -170,9 +170,8 @@@ private
      MediaSplicerPtr mSplicer;
      ExecutorPtr mActivities;
      AsteriskSCF::SessionCommunications::V1::SessionControllerPrx mSessionController;
+     AsteriskSCF::SessionCommunications::PartyIdentification::V1::ConnectedLinePtr mConnectedLine;
+     bool mConnectedLineSet;
 -   
  
      /**
       * Sends changes to the replication service. This should never occur
diff --cc test/CMakeLists.txt
index f9fcf25,9773c64..979d462
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@@ -31,7 -30,7 +30,8 @@@ astscf_component_add_files(bridge_unit_
  astscf_component_add_files(bridge_unit_tests ../src/SessionOperations.cpp)
  astscf_component_add_files(bridge_unit_tests ../src/SessionWrapper.cpp)
  astscf_component_add_files(bridge_unit_tests ../src/MediaSplicer.cpp)
 +astscf_component_add_files(bridge_unit_tests ../src/MediaMixer.cpp)
+ astscf_component_add_slices(bridge_unit_tests PROJECT AsteriskSCF/Replication/BridgeService/BridgeReplicatorIf.ice)
  astscf_component_add_files(bridge_unit_tests UnitTests.cpp)
  astscf_component_add_ice_libraries(bridge_unit_tests Ice)
  astscf_component_add_boost_libraries(bridge_unit_tests unit_test_framework thread)

commit 1e99ad99de150e86169a828a6341717dad05e110
Author: Ken Hunt <ken.hunt at digium.com>
Date:   Sun Oct 2 17:53:26 2011 -0500

    Added connect/disconnect of telephony event sources and sinks.

diff --git a/src/BridgeImpl.cpp b/src/BridgeImpl.cpp
index 36ea2dd..0c94a05 100755
--- a/src/BridgeImpl.cpp
+++ b/src/BridgeImpl.cpp
@@ -973,6 +973,175 @@ private:
     BridgeImplPtr mBridge;
 };
 
+class ConnectTelephonyEventsTask: public QueuedTask
+{
+public:
+    ConnectTelephonyEventsTask(const BridgeImplPtr& bridge,
+                               const SessionSeq& newSessions,
+                               const Logger& logger) 
+       : QueuedTask("ConnectTelephonyEventsTask"), 
+         mBridge(bridge), 
+         mNewSessions(newSessions), 
+         mLogger(logger) 
+    { 
+    }
+
+protected:
+    bool executeImpl()
+    {
+        vector<TelephonySessionPrx> ignoreList;
+
+        // Assumption: All the sessions we need to connect to are already 
+        // part of the bridge's session collection. 
+        for (SessionSeq::iterator i = mNewSessions.begin(); i != mNewSessions.end(); ++i)
+        {
+            TelephonySessionPrx telephonySession;
+            try
+            {
+                telephonySession = TelephonySessionPrx::checkedCast(*i);
+            }
+            catch(...)
+            {
+                continue;
+            }
+
+            if (telephonySession == 0)
+            {
+                continue;
+            }
+
+            ConnectTelephonyOperation op(telephonySession, ignoreList, mLogger);
+            mBridge->getSessions()->visitSessions(op);
+
+            // Since this session is now connected to all others in the bridge (including
+            // those in the mNewSessions set) we don't need to connect this one again.
+            ignoreList.push_back(telephonySession);
+        }
+        return true;
+    }
+
+private:
+    BridgeImplPtr mBridge;
+    SessionSeq mNewSessions;
+    Logger mLogger;
+};
+
+class DisconnectTelephonyEventsTask: public QueuedTask
+{
+public:
+    DisconnectTelephonyEventsTask(const BridgeImplPtr& bridge,
+                               const SessionSeq& disconnectingSessions,
+                               const Logger& logger) 
+       : QueuedTask("DisconnectTelephonyEventsTask"), 
+         mBridge(bridge), 
+         mDisconnectingSessions(disconnectingSessions), 
+         mLogger(logger) 
+    { 
+    }
+
+protected:
+    bool executeImpl()
+    {
+        for (SessionSeq::iterator i = mDisconnectingSessions.begin(); i != mDisconnectingSessions.end(); ++i)
+        {
+            TelephonySessionPrx telephonySession;
+            try
+            {
+                telephonySession = TelephonySessionPrx::checkedCast(*i);
+            }
+            catch(...)
+            {
+                continue;
+            }
+
+            if (telephonySession == 0)
+            {
+                continue;
+            }
+
+            DisconnectTelephonyOperation op(telephonySession, mLogger);
+            mBridge->getSessions()->visitSessions(op);
+        }
+
+        /**
+         * In ConnectTelephonyEventsTask, we could assume all the sessions were in the bridge's session collection
+         * and just use a visitor. But when a session is removed, AMI operations are involved. We use an 
+         * extra pass over the set of sessions being removed, and disconnect each one from the other, to be safe. 
+         */
+        disconnectMembers();
+
+        return true;
+    }
+
+    /**
+     * Disconnect the members of mDisconnectingSessions from each other.
+     */
+    void disconnectMembers()
+    {
+        for(SessionSeq::iterator i = mDisconnectingSessions.begin();
+            i != mDisconnectingSessions.end(); ++i)
+        {
+            TelephonySessionPrx session1 = TelephonySessionPrx::checkedCast(*i);
+            if (session1 == 0)
+            {
+                // If not a telephony session, nothing to do. 
+                continue;
+            }
+
+            disconnectMembersFrom(session1);
+        }
+    }
+
+    void disconnectMembersFrom(TelephonySessionPrx session1)
+    {
+        for(SessionSeq::iterator i = mDisconnectingSessions.begin();
+            i != mDisconnectingSessions.end(); ++i)
+        {
+            if (session1->ice_getIdentity() == (*i)->ice_getIdentity())
+            {
+                // It's not connected to itself.
+                continue;
+            }
+
+            TelephonySessionPrx session2 = TelephonySessionPrx::checkedCast(*i);
+            if (session2== 0)
+            {
+                // If not a telephony session, nothing to do. 
+                continue;
+            }
+
+            disconnectSinks(session1, session2);
+            disconnectSinks(session2, session1);
+        }
+    }
+
+    void disconnectSinks
+        (const TelephonySessionPrx& sourceSession, 
+         const TelephonySessionPrx& sinkSession)
+    {
+        if (sourceSession->ice_getIdentity() == sinkSession->ice_getIdentity())
+        {
+            // Not connected to ourselves.
+            return;
+        }
+
+        TelephonyEventSinkSeq sinksToRemove = sinkSession->getSinks();
+        TelephonyEventSourceSeq fromSources = sourceSession->getSources();
+
+        for(TelephonyEventSourceSeq::iterator i=fromSources.begin();   
+            i != fromSources.end(); ++i)
+        {
+                (*i)->removeSinks(sinksToRemove);
+        }
+    }
+
+private:
+    BridgeImplPtr mBridge;
+    SessionSeq mDisconnectingSessions;
+    Logger mLogger;
+};
+
+
 } // End of anonymous namespace
 
 BridgeImpl::BridgeImpl(const string& name, const Ice::ObjectAdapterPtr& adapter, 
@@ -1082,6 +1251,7 @@ void BridgeImpl::addSessions_async(const AMD_Bridge_addSessionsPtr& callback, co
 	tasks.push_back(new SetAndGetSessionControllerTask(mObjAdapter, mSessions, sessions, this, mLogger));
         tasks.push_back(new GenericAMDCallback<AMD_Bridge_addSessionsPtr>(callback, tracker));
         tasks.push_back(new SetupMedia(this));
+        tasks.push_back(new ConnectTelephonyEventsTask(this, sessions, mLogger));
         tasks.push_back(new UpdateTask(this));
         ExecutorPtr executor(new Executor(tasks, mLogger));
         executor->start();
@@ -1141,6 +1311,7 @@ void BridgeImpl::removeSessions_async(const AMD_Bridge_removeSessionsPtr& callba
         }
         tasks.push_back(new RemoveSessionsNotify(mListeners, removed, cookies));
         tasks.push_back(new GenericAMDCallback<AMD_Bridge_removeSessionsPtr>(callback, removed));
+        tasks.push_back(new DisconnectTelephonyEventsTask(this, sessions, mLogger));
         tasks.push_back(new CheckShutdown(this, mPrx));
         ExecutorPtr runner(new Executor(tasks, mLogger));
         runner->start();
@@ -1342,6 +1513,10 @@ void BridgeImpl::replaceSession_async(const AMD_Bridge_replaceSessionPtr& callba
             boost::shared_lock<boost::shared_mutex> lock(mLock);
             cookies = getCookies();
         }
+
+        SessionSeq removedSessions;
+        removedSessions.push_back(sessionToReplace);
+
         tasks.push_back(new RemoveSessionsNotify(mListeners, removeTracker, cookies));
         tasks.push_back(new UnplugMedia(this));
         tasks.push_back(new SetBridgeTask(mSessions, mPrx, mSessionListenerPrx, newSessions, tracker));
@@ -1349,6 +1524,8 @@ void BridgeImpl::replaceSession_async(const AMD_Bridge_replaceSessionPtr& callba
 	tasks.push_back(new SetAndGetSessionControllerTask(mObjAdapter, mSessions, newSessions, this, mLogger));
         tasks.push_back(new GenericAMDCallback<AMD_Bridge_replaceSessionPtr>(callback, tracker));
         tasks.push_back(new SetupMedia(this));
+        tasks.push_back(new ConnectTelephonyEventsTask(this, newSessions, mLogger));
+        tasks.push_back(new DisconnectTelephonyEventsTask(this, removedSessions, mLogger));
         tasks.push_back(new UpdateTask(this));
         ExecutorPtr executor(new Executor(tasks, mLogger));
         executor->start();
@@ -1575,6 +1752,7 @@ void BridgeImpl::getAddSessionsTasks(QueuedTasks& tasks,
     tasks.push_back(new AddToListeners(mListeners, tracker, getCookies()));
     tasks.push_back(new SetAndGetSessionControllerTask(mObjAdapter, mSessions, sessions, this, mLogger));
     tasks.push_back(new SetupMedia(this));
+    tasks.push_back(new ConnectTelephonyEventsTask(this, sessions, mLogger));
     tasks.push_back(new UpdateTask(this));
 }
 
diff --git a/src/SessionOperations.cpp b/src/SessionOperations.cpp
index e6bf5f8..38c0184 100644
--- a/src/SessionOperations.cpp
+++ b/src/SessionOperations.cpp
@@ -233,3 +233,106 @@ void RemoveStreamsOperation::removed(const SessionWrapperPtr& session)
 void RemoveStreamsOperation::failed(const Ice::Exception&, const SessionWrapperPtr&)
 {
 }
+
+ConnectTelephonyOperation::ConnectTelephonyOperation(const TelephonySessionPrx& sessionToConnect,
+                                                     const vector<TelephonySessionPrx>& ignoreList,
+                                                     const Logger& logger)
+                                                       : mSessionToConnect(sessionToConnect),
+                                                         mIgnoreList(ignoreList),
+                                                         mLogger(logger)
+{
+}
+
+void ConnectTelephonyOperation::operator()(const SessionWrapperPtr& session)
+{
+    if (session->getSession()->ice_getIdentity() == mSessionToConnect->ice_getIdentity())
+    {
+        // Let's not connect a session to itself. . 
+        return;
+    }
+
+    TelephonySessionPrx visitedTelephonySession = TelephonySessionPrx::checkedCast(session->getSession());
+    if (visitedTelephonySession == 0)
+    {
+        // If the session being visited isn't telephony, nothing to do. 
+        return;
+    }
+
+    if (inIgnoreList(visitedTelephonySession))
+    {
+        return;
+    }
+
+    connectSinks(mSessionToConnect, visitedTelephonySession);
+    connectSinks(visitedTelephonySession, mSessionToConnect);
+
+}
+
+bool ConnectTelephonyOperation::inIgnoreList(const TelephonySessionPrx& session)
+{
+    for(vector<TelephonySessionPrx>::iterator i=mIgnoreList.begin();   
+        i != mIgnoreList.end(); ++i)
+    {
+        if (session->ice_getIdentity() == (*i)->ice_getIdentity())
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+void ConnectTelephonyOperation::connectSinks
+    (const TelephonySessionPrx& sourceSession, 
+     const TelephonySessionPrx& sinkSession)
+{
+    TelephonyEventSinkSeq sinksToAdd = sinkSession->getSinks();
+    TelephonyEventSourceSeq toSources = sourceSession->getSources();
+
+    for(TelephonyEventSourceSeq::iterator i=toSources.begin();   
+        i != toSources.end(); ++i)
+    {
+            (*i)->addSinks(sinksToAdd);
+    }
+}
+
+DisconnectTelephonyOperation::DisconnectTelephonyOperation(const TelephonySessionPrx& sessionToDisconnect,
+                                                           const Logger& logger)
+                                                       : mSessionToDisconnect(sessionToDisconnect),
+                                                         mLogger(logger)
+{
+}
+
+void DisconnectTelephonyOperation::operator()(const SessionWrapperPtr& visitedSession)
+{
+    if (visitedSession->getSession()->ice_getIdentity() == mSessionToDisconnect->ice_getIdentity())
+    {
+        // Not connected to ourselves.
+        return;
+    }
+
+    TelephonySessionPrx visitedTelephonySession = TelephonySessionPrx::checkedCast(visitedSession->getSession());
+    if (visitedTelephonySession == 0)
+    {
+        // If the session being visited isn't telephony, nothing to do. 
+        return;
+    }
+
+    disconnectSinks(mSessionToDisconnect, visitedTelephonySession);
+    disconnectSinks(visitedTelephonySession, mSessionToDisconnect);
+
+}
+
+void DisconnectTelephonyOperation::disconnectSinks
+    (const TelephonySessionPrx& sourceSession, 
+     const TelephonySessionPrx& sinkSession)
+{
+    TelephonyEventSinkSeq sinksToRemove = sinkSession->getSinks();
+    TelephonyEventSourceSeq fromSources = sourceSession->getSources();
+
+    for(TelephonyEventSourceSeq::iterator i=fromSources.begin();   
+        i != fromSources.end(); ++i)
+    {
+            (*i)->removeSinks(sinksToRemove);
+    }
+}
diff --git a/src/SessionOperations.h b/src/SessionOperations.h
index a4e2c29..042fdce 100644
--- a/src/SessionOperations.h
+++ b/src/SessionOperations.h
@@ -117,6 +117,44 @@ private:
 
 typedef IceUtil::Handle<AddStreamsOperation> AddStreamsOperationPtr;
 
+class ConnectTelephonyOperation : public std::unary_function<SessionWrapperPtr, void>, public Ice::Object
+{
+public:
+    ConnectTelephonyOperation(const AsteriskSCF::SessionCommunications::V1::TelephonySessionPrx& sessionToConnect,
+                              const std::vector<AsteriskSCF::SessionCommunications::V1::TelephonySessionPrx>& ignoreList,
+                              const AsteriskSCF::System::Logging::Logger& logger);
+
+    void operator()(const SessionWrapperPtr& session);
+
+private:
+    void connectSinks(const AsteriskSCF::SessionCommunications::V1::TelephonySessionPrx& sourceSession, 
+                      const AsteriskSCF::SessionCommunications::V1::TelephonySessionPrx& sinkSession);
+
+    bool inIgnoreList(const AsteriskSCF::SessionCommunications::V1::TelephonySessionPrx& session);
+
+    AsteriskSCF::SessionCommunications::V1::TelephonySessionPrx mSessionToConnect;
+    std::vector<AsteriskSCF::SessionCommunications::V1::TelephonySessionPrx> mIgnoreList;
+    AsteriskSCF::System::Logging::Logger mLogger;
+};
+typedef IceUtil::Handle<ConnectTelephonyOperation> ConnectTelephonyOperationPtr;
+
+class DisconnectTelephonyOperation : public std::unary_function<SessionWrapperPtr, void>, public Ice::Object
+{
+public:
+    DisconnectTelephonyOperation(const AsteriskSCF::SessionCommunications::V1::TelephonySessionPrx& sessionToDisconnect,
+                                 const AsteriskSCF::System::Logging::Logger& logger);
+
+    void operator()(const SessionWrapperPtr& session);
+
+private:
+    void disconnectSinks(const AsteriskSCF::SessionCommunications::V1::TelephonySessionPrx& sourceSession, 
+                         const AsteriskSCF::SessionCommunications::V1::TelephonySessionPrx& sinkSession);
+
+    AsteriskSCF::SessionCommunications::V1::TelephonySessionPrx mSessionToDisconnect;
+    AsteriskSCF::System::Logging::Logger mLogger;
+};
+typedef IceUtil::Handle<DisconnectTelephonyOperation> DisconnectTelephonyOperationPtr;
+
 class RemoveStreamsOperation : public std::unary_function<SessionWrapperPtr, void>, public Ice::Object
 {
 public:
diff --git a/test/TestBridging.cpp b/test/TestBridging.cpp
index b7efa3f..0476241 100644
--- a/test/TestBridging.cpp
+++ b/test/TestBridging.cpp
@@ -1351,6 +1351,105 @@ public:
         }
     }
 
+    void telephonyConnectTest()
+    {
+        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()));
+
+                BridgeManagerPrx mgrPrx = env()->primaryBridgeManager();
+                BOOST_CHECK(mgrPrx);
+                mgrPrx->addListener(listenerPrx);
+
+                SessionSeq sessions;
+                TestChannelWrapper channel(env()->properties());
+
+                SessionPrx a = channel.getSession("311");
+                TelephonySessionPrx ta = TelephonySessionPrx::checkedCast(a);
+                BOOST_CHECK(ta != 0);
+
+                TelephonyEventSourceSeq aSources = ta->getSources();
+                TelephonyEventSinkSeq aSinks = ta->getSinks();
+                BOOST_CHECK(aSources.size() == 1);
+                BOOST_CHECK(aSinks.size() == 1);
+                TelephonyEventSinkSeq aConnected = aSources[0]->getSinks();
+                BOOST_CHECK(aConnected.size() == 0);
+
+                SessionPrx b = channel.getSession("312");
+                TelephonySessionPrx tb = TelephonySessionPrx::checkedCast(b);
+                BOOST_CHECK(tb != 0);
+
+                TelephonyEventSourceSeq bSources = tb->getSources();
+                TelephonyEventSinkSeq bSinks = tb->getSinks();
+                BOOST_CHECK(bSources.size() == 1);
+                BOOST_CHECK(bSinks.size() == 1);
+                TelephonyEventSinkSeq bConnected = bSources[0]->getSinks();
+                BOOST_CHECK(bConnected.size() == 0);
+
+                sessions.push_back(a);
+                sessions.push_back(b);
+                BridgePrx bridge(mgrPrx->createBridge(sessions, 0));
+
+                IceUtil::ThreadControl::sleep(IceUtil::Time::seconds(2));
+
+                // Now that we're bridged, insure the sinks are connected as expected.
+                aConnected = aSources[0]->getSinks();
+                BOOST_CHECK(aConnected.size() == 1);
+                BOOST_CHECK(aConnected[0]->ice_getIdentity() == bSinks[0]->ice_getIdentity());
+
+                bConnected = bSources[0]->getSinks();
+                BOOST_CHECK(bConnected.size() == 1);
+                BOOST_CHECK(bConnected[0]->ice_getIdentity() == aSinks[0]->ice_getIdentity());
+
+                SessionPrx c = channel.getSession("314");
+                TelephonySessionPrx tc = TelephonySessionPrx::checkedCast(c);
+                BOOST_CHECK(tc != 0);
+
+                sessions.clear();
+                sessions.push_back(c);
+                TelephonyEventSourceSeq cSources = tc->getSources();
+                TelephonyEventSinkSeq cSinks = tc->getSinks();
+
+                bridge->replaceSession(b, sessions);
+
+                IceUtil::ThreadControl::sleep(IceUtil::Time::seconds(2));
+
+                // We've replaced b with c. Make sure all is well, including disconnecting b. 
+                aConnected = aSources[0]->getSinks();
+                BOOST_CHECK(aConnected.size() == 1);
+                BOOST_CHECK(aConnected[0]->ice_getIdentity() == cSinks[0]->ice_getIdentity());
+
+                TelephonyEventSinkSeq cConnected = cSources[0]->getSinks();
+                BOOST_CHECK(cConnected.size() == 1);
+                BOOST_CHECK(cConnected[0]->ice_getIdentity() == aSinks[0]->ice_getIdentity());
+
+                bConnected = bSources[0]->getSinks();
+                BOOST_CHECK(bConnected.size() == 0);
+            }
+            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;
 };
@@ -1361,6 +1460,8 @@ bool init_unit_test()
 {
     boost::shared_ptr<BridgeTester> bridgeTester(new BridgeTester(globalTestEnvironment));
     framework::master_test_suite().
+        add(BOOST_TEST_CASE(boost::bind(&BridgeTester::telephonyConnectTest, bridgeTester)));
+    framework::master_test_suite().
         add(BOOST_TEST_CASE(boost::bind(&BridgeTester::createEmptyBridge, bridgeTester)));
     framework::master_test_suite().
         add(BOOST_TEST_CASE(boost::bind(&BridgeTester::simpleBridgingTest, bridgeTester)));

commit 7d67896288e9087ba634e48430f0417f3e3e1526
Author: Ken Hunt <ken.hunt at digium.com>
Date:   Fri Sep 30 19:00:08 2011 -0500

    Removed names of unused params, matched initializer list to variable decl order, etc.

diff --git a/src/BridgePartyIdExtensionPoint.cpp b/src/BridgePartyIdExtensionPoint.cpp
index 60aa335..a648288 100644
--- a/src/BridgePartyIdExtensionPoint.cpp
+++ b/src/BridgePartyIdExtensionPoint.cpp
@@ -66,11 +66,11 @@ public:
     virtual void replaceHooks(const AsteriskSCF::Replication::BridgeService::V1::PartyIdHooksPtr& hooks);
 
 private:
+    Logger mLogger;
+
     ProxySet<ReceivedConnectedLinePartyIdHookPrx>::SetPtr mReceiveConnectedLineHooks;
     ProxySet<ForwardingConnectedLinePartyIdHookPrx>::SetPtr mForwardingConnectedLineHooks;
     ProxySet<ForwardingRedirectionsPartyIdHookPrx>::SetPtr mForwardingRedirectionsHooks;
-
-    Logger mLogger;
 };
 
 } // end anon namespace
@@ -88,47 +88,47 @@ BridgePartyIdExtensionPointImpl::BridgePartyIdExtensionPointImpl(
 // PartyIdentificationExtensionPoint API implementation
 void BridgePartyIdExtensionPointImpl::addReceivedConnectedLinePartyIdHook(
     const ::AsteriskSCF::SessionCommunications::ExtensionPoints::V1::ReceivedConnectedLinePartyIdHookPrx& hook,
-    const Ice::Current& current)
+    const Ice::Current&)
 {
     mReceiveConnectedLineHooks->add(hook);
 }
 
 void BridgePartyIdExtensionPointImpl::addForwardingConnectedLinePartyIdHook(
     const ::AsteriskSCF::SessionCommunications::ExtensionPoints::V1::ForwardingConnectedLinePartyIdHookPrx& hook,
-    const Ice::Current& current)
+    const Ice::Current&)
 {
     mForwardingConnectedLineHooks->add(hook);
 }
 
 void BridgePartyIdExtensionPointImpl::addForwardingRedirectionsPartyIdHook(
     const ::AsteriskSCF::SessionCommunications::ExtensionPoints::V1::ForwardingRedirectionsPartyIdHookPrx& hook,
-    const Ice::Current& current)
+    const Ice::Current&)
 {
     mForwardingRedirectionsHooks->add(hook);
 }
 
 void BridgePartyIdExtensionPointImpl::removeReceivedConnectedLinePartyIdHook(
     const ::AsteriskSCF::SessionCommunications::ExtensionPoints::V1::ReceivedConnectedLinePartyIdHookPrx& hook,
-    const Ice::Current& current)
+    const Ice::Current&)
 {
     mReceiveConnectedLineHooks->remove(hook);
 }
 
 void BridgePartyIdExtensionPointImpl::removeForwardingConnectedLinePartyIdHook(
     const ::AsteriskSCF::SessionCommunications::ExtensionPoints::V1::ForwardingConnectedLinePartyIdHookPrx& hook,
-    const Ice::Current& current)
+    const Ice::Current&)
 {
     mForwardingConnectedLineHooks->remove(hook);
 }
 
 void BridgePartyIdExtensionPointImpl::removeForwardingRedirectionsPartyIdHook(
     const ::AsteriskSCF::SessionCommunications::ExtensionPoints::V1::ForwardingRedirectionsPartyIdHookPrx& hook,
-    const Ice::Current& current)
+    const Ice::Current&)
 {
     mForwardingRedirectionsHooks->remove(hook);
 }
 
-void BridgePartyIdExtensionPointImpl::clearPartyIdentificationHooks(const Ice::Current& current)
+void BridgePartyIdExtensionPointImpl::clearPartyIdentificationHooks(const Ice::Current&)
 {
     mReceiveConnectedLineHooks->clear();
     mForwardingConnectedLineHooks->clear();

commit bf4b6cc530ddcf99d7177913073b97433cb3b5d5
Author: Ken Hunt <ken.hunt at digium.com>
Date:   Fri Sep 30 17:41:46 2011 -0500

    Support for Party Id modifying extension point.

diff --git a/slice/AsteriskSCF/Replication/BridgeService/BridgeReplicatorIf.ice b/slice/AsteriskSCF/Replication/BridgeService/BridgeReplicatorIf.ice
index 0eb53de..e360795 100644
--- a/slice/AsteriskSCF/Replication/BridgeService/BridgeReplicatorIf.ice
+++ b/slice/AsteriskSCF/Replication/BridgeService/BridgeReplicatorIf.ice
@@ -17,6 +17,7 @@
 
 #include <Ice/BuiltinSequences.ice>
 #include <AsteriskSCF/SessionCommunications/SessionCommunicationsIf.ice>
+#include <AsteriskSCF/SessionCommunications/SessionCommunicationsExtensionPointsIf.ice>
 #include <AsteriskSCF/Core/Discovery/ServiceLocatorIf.ice>
 #include <AsteriskSCF/Media/MediaIf.ice>
 
@@ -163,7 +164,17 @@ enum ServiceState
     Destroyed
 };
 sequence<AsteriskSCF::SessionCommunications::V1::BridgeManagerListener*> BridgeManagerListenerSeq;
-    
+
+/**
+ * Collection of party id hooks.
+ */
+class PartyIdHooks
+{
+    AsteriskSCF::SessionCommunications::ExtensionPoints::V1::ReceivedConnectedLinePartyIdHookSeq receivedConnectedLineHooks;
+    AsteriskSCF::SessionCommunications::ExtensionPoints::V1::ForwardingConnectedLinePartyIdHookSeq forwardingConnectedLineHooks;
+    AsteriskSCF::SessionCommunications::ExtensionPoints::V1::ForwardingRedirectionsPartyIdHookSeq forwardingRedirectionsHooks;
+};
+
 /**
  * The bridge manager state.
  **/
@@ -172,6 +183,7 @@ class BridgeManagerStateItem extends ReplicatedStateItem
     ServiceState runningState;
     AsteriskSCF::SessionCommunications::V1::BridgeListenerSeq defaultBridgeListeners;
     BridgeManagerListenerSeq listeners;
+    PartyIdHooks partyIdExtensionPointHooks;
 };
 
 /**
@@ -200,6 +212,12 @@ class BridgeStateItem extends ReplicatedStateItem
     MediaOperationReplicationPolicy mediaReplicationPolicy;
 
     AsteriskSCF::SessionCommunications::V1::BridgeCookieDict cookies;
+
+    /**
+     * Since the hooks can change over time, each bridge gets
+     * its own snapshot of applicable hooks. 
+     */
+    PartyIdHooks partyIdHookSet;
 };
 
 class BridgeListenerStateItem extends ReplicatedStateItem
diff --git a/src/BridgeImpl.cpp b/src/BridgeImpl.cpp
index edcd46b..36ea2dd 100755
--- a/src/BridgeImpl.cpp
+++ b/src/BridgeImpl.cpp
@@ -33,6 +33,7 @@
 using namespace AsteriskSCF::System::Logging;
 using namespace AsteriskSCF::SessionCommunications::V1;
 using namespace AsteriskSCF::SessionCommunications::PartyIdentification::V1;
+using namespace AsteriskSCF::SessionCommunications::ExtensionPoints::V1;
 using namespace AsteriskSCF::BridgeService;
 using namespace AsteriskSCF::Replication::BridgeService::V1;
 using namespace AsteriskSCF;
@@ -121,6 +122,11 @@ public:
 
     void getAddSessionsTasks(QueuedTasks& tasks, const SessionSeq& sessions);
 
+    PartyIdHooksPtr getPartyIdHooks()
+    {
+        return mState->partyIdHookSet;
+    }
+
     BridgeCookies getCookies()
     {
         BridgeCookies result;
@@ -131,6 +137,9 @@ public:
         return result;
     }
 
+    void updateConnectedLine(const SessionWrapperPtr& sourceSession, const ConnectedLinePtr& connectedLine);
+    void updateRedirections(const SessionWrapperPtr& sourceSession, const RedirectionsPtr& redirections);
+
 private:
 
     boost::shared_mutex mLock;
@@ -261,6 +270,273 @@ private:
 };
 typedef IceUtil::Handle<SessionsTracker> SessionsTrackerPtr;
 
+
+/**
+ * Forwards the redirection records for the specified session
+ * to every other session in the bridge. Applies the 
+ * ForwardingRedirections hooks to the Redirections record
+ * in the process. 
+ *
+ * Note: For now we forward the Redirections record 
+ * (with possible hook modifications) 
+ * without considering whether there are more than two
+ * sessions in the bridge. 
+ */
+class ForwardRedirectionsUpdatedTask : public QueuedTask
+{
+public:
+    ForwardRedirectionsUpdatedTask(const BridgeImplPtr& bridge, 
+            const SessionWrapperPtr& sourceSession,
+            const RedirectionsPtr& redirections,
+            const Logger& logger) :
+        QueuedTask("ForwardRedirectionsUpdatedTask"),
+        mBridge(bridge),
+        mSourceSession(sourceSession),
+        mRedirections(redirections),
+        mLogger(logger)
+    {
+    }
+    
+protected:
+    bool executeImpl()
+    {
+        try
+        {
+            mLogger(Debug) << FUNLOG;
+
+            // Forward the ConnectedLine to each bridged session.
+            SessionSeq sessions = mBridge->getSessions()->getSessionSeq();
+            for(SessionSeq::iterator i = sessions.begin();
+                i != sessions.end(); ++i)
+            {
+                if ((*i)->ice_getIdentity() == mSourceSession->getSession()->ice_getIdentity())
+                {
+                    continue;
+                }
+
+                SessionWrapperPtr destSessionWrapper = mBridge->getSessions()->getSession(*i);
+                forward(destSessionWrapper, mRedirections);
+            }
+
+        }
+        catch (const std::exception e)
+        {
+            mLogger(Debug) << FUNLOG << " : " << e.what();
+        }
+
+        return true;
+    }
+           
+    void forward(const SessionWrapperPtr destinationSession, const RedirectionsPtr& redirections)
+    {
+        mLogger(Debug) << FUNLOG;
+
+        RedirectionsPtr currentRedirections = redirections;
+        RedirectionsPtr destSpecificRedirections = redirections;
+
+        PartyIdHooksPtr partyIdHooks = mBridge->getPartyIdHooks();
+
+        // Allow the ForwardingRedirectionsPartyId hooks to alter the Redirections record. 
+        for(vector<ForwardingRedirectionsPartyIdHookPrx>::const_iterator i = partyIdHooks->forwardingRedirectionsHooks.begin();
+            i != partyIdHooks->forwardingRedirectionsHooks.end(); ++i)
+        {
+            try
+            {
+                // Apply this hook. 
+                AsteriskSCF::System::Hook::V1::HookResult hookResult = (*i)->modifyForwardingRedirections(mSourceSession->getSession(),
+                    destinationSession->getSession(),
+                    currentRedirections, destSpecificRedirections);
+
+                if (hookResult.status == AsteriskSCF::System::Hook::V1::Succeeded)
+                {
+                    currentRedirections = destSpecificRedirections;
+                }
+            }
+            catch(const std::exception& e)
+            {
+                mLogger(Warning) << FUNLOG << " : " << e.what();
+            }
+        }
+
+        // Forward the info via the SessionController for this session.
+        destinationSession->getSessionController()->updateRedirections(currentRedirections);
+    }
+
+private:
+    BridgeImplPtr mBridge;
+    SessionWrapperPtr mSourceSession;
+    RedirectionsPtr mRedirections;
+    Logger mLogger;
+};
+
+/**
+ * Sends the cached ConnectedLine info for the specified session
+ * to every other session in the bridge. Applies the 
+ * ForwardingConnectedLine hooks to the ConnectedLine record
+ * in the process. 
+ *
+ * Note: For now we forward the ConnectedLine record 
+ * without considering whether there are more than two
+ * sessions in the bridge. The API may need a more complex 
+ * class than ConnectedLine to push the state
+ * of more than one Session. 
+ */
+class ForwardConnectedLineTask : public QueuedTask
+{
+public:
+    ForwardConnectedLineTask(const BridgeImplPtr& bridge, 
+            const SessionWrapperPtr& sourceSession,
+            const Logger& logger) :
+        QueuedTask("ForwardConnectedLineTask"),
+        mBridge(bridge),
+        mSourceSession(sourceSession),
+        mLogger(logger)
+    {
+    }
+    
+protected:
+    bool executeImpl()
+    {
+        try
+        {
+            mLogger(Debug) << FUNLOG;
+
+            ConnectedLinePtr currentConnectedLine;
+            bool isSet = mSourceSession->getConnectedLine(currentConnectedLine);
+
+            if (!isSet)
+            {
+                mLogger(Error) << "ConnectedLine not cached for forwarding. " ;
+                return true; 
+            }
+
+            // Forward the ConnectedLine to each bridged session.
+            SessionSeq sessions = mBridge->getSessions()->getSessionSeq();
+            for(SessionSeq::iterator i = sessions.begin();
+                i != sessions.end(); ++i)
+            {
+                if ((*i)->ice_getIdentity() == mSourceSession->getSession()->ice_getIdentity())
+                {
+                    continue;
+                }
+
+                SessionWrapperPtr destSessionWrapper = mBridge->getSessions()->getSession(*i);
+                forward(destSessionWrapper, currentConnectedLine);
+            }
+
+        }
+        catch (const std::exception e)
+        {
+            mLogger(Debug) << FUNLOG << " : " << e.what();
+        }
+
+        return true;
+    }
+           
+    void forward(const SessionWrapperPtr destinationSession, const ConnectedLinePtr& connectedLine)
+    {
+        mLogger(Debug) << FUNLOG;
+
+        ConnectedLinePtr currentConnectedLine = connectedLine;
+        ConnectedLinePtr destSpecificConnectedLine = connectedLine;
+
+        PartyIdHooksPtr partyIdHooks = mBridge->getPartyIdHooks();
+
+        // Allow the ForwardingConnectedLinePartyId hooks to alter the ConnectedLine record. 
+        for(vector<ForwardingConnectedLinePartyIdHookPrx>::const_iterator i = partyIdHooks->forwardingConnectedLineHooks.begin();
+            i != partyIdHooks->forwardingConnectedLineHooks.end(); ++i)
+        {
+            try
+            {
+                // Apply a hook
+                AsteriskSCF::System::Hook::V1::HookResult hookResult = (*i)->modifyForwardingConnectedLine(mSourceSession->getSession(),
+                    destinationSession->getSession(),
+                    currentConnectedLine, destSpecificConnectedLine);
+
+                if (hookResult.status == AsteriskSCF::System::Hook::V1::Succeeded)
+                {
+                    currentConnectedLine = destSpecificConnectedLine;
+                }
+            }
+            catch (const std::exception e)
+            {
+                mLogger(Debug) << FUNLOG << " : " << e.what();
+            }
+        }
+
+        // Forward the info via the SessionController for this session.
+        destinationSession->getSessionController()->updateConnectedLine(currentConnectedLine);
+    }
+
+private:
+    BridgeImplPtr mBridge;
+    SessionWrapperPtr mSourceSession;
+    Logger mLogger;
+};
+
+/**
+ * Applies the ReceiveConnectedLine hooks to the new ConnectedLine
+ * information before caching it for the specified session. 
+ */
+class UpdateConnectedLineTask : public QueuedTask
+{
+public:
+    UpdateConnectedLineTask(const BridgeImplPtr& bridge, 
+            const SessionWrapperPtr& sourceSession,
+            const ConnectedLinePtr& connectedLine,
+            const Logger& logger) :
+        QueuedTask("UpdateConnectedLineTask"),
+        mBridge(bridge),
+        mSourceSession(sourceSession),
+        mConnectedLine(connectedLine),
+        mLogger(logger)
+    {
+    }
+    
+protected:
+    bool executeImpl()
+    {
+        mLogger(Debug) << FUNLOG;
+
+        ConnectedLinePtr currentConnectedLine = mConnectedLine;
+        ConnectedLinePtr updatedConnectedLine = mConnectedLine;
+
+        PartyIdHooksPtr partyIdHooks = mBridge->getPartyIdHooks();
+
+        // Allow the ReceivedConnectedLinePartyId hooks to alter the ConnectedLine record. 
+        for(vector<ReceivedConnectedLinePartyIdHookPrx>::const_iterator i = partyIdHooks->receivedConnectedLineHooks.begin();
+            i != partyIdHooks->receivedConnectedLineHooks.end(); ++i)
+        {
+            try
+            {
+                // Apply this hook. 
+                AsteriskSCF::System::Hook::V1::HookResult hookResult = (*i)->modifyReceivedConnectedLine(mSourceSession->getSession(),
+                    currentConnectedLine, updatedConnectedLine);
+
+                if (hookResult.status == AsteriskSCF::System::Hook::V1::Succeeded)
+                {
+                    currentConnectedLine = updatedConnectedLine;
+                }
+            }
+            catch (const std::exception e)
+            {
+                mLogger(Debug) << FUNLOG << " : " << e.what();
+            }
+        }
+
+        // Cache this value.
+        mSourceSession->setConnectedLine(currentConnectedLine);
+
+        return true;
+    }
+           
+private:
+    BridgeImplPtr mBridge;
+    SessionWrapperPtr mSourceSession;
+    ConnectedLinePtr mConnectedLine;
+    Logger mLogger;
+};
+
 class RemoveSessionsNotify : public QueuedTask
 {
 public:
@@ -415,14 +691,14 @@ public:
         cb->ice_response();
     }
 
-    void updateConnectedLine(const ConnectedLinePtr&, const Ice::Current&)
+    void updateConnectedLine(const ConnectedLinePtr& connectedLine, const Ice::Current&)
     {
-        // TBD
+        mBridge->updateConnectedLine(mSelf, connectedLine);
     }
 
-    void updateRedirecting(const RedirectingPtr&, const ::Ice::Current&) 
+    void updateRedirections(const RedirectionsPtr& redirections, const ::Ice::Current&) 
     {
-        // TBD
+        mBridge->updateRedirections(mSelf, redirections);
     }
 
 private:
@@ -732,6 +1008,54 @@ BridgeImpl::~BridgeImpl()
     //
 }
 
+/** 
+ * Process an updated ConnectedLine record from a session. 
+ */
+void BridgeImpl::updateConnectedLine(const SessionWrapperPtr& sourceSession, const ConnectedLinePtr& connectedLine)
+{
+     try
+    {
+        QueuedTasks tasks;
+
+        // Updates the cached ConnectedLine party id information for the given session.
+        //  - Applies receive hooks on the received ConnectedLine info before caching.
+        tasks.push_back(new UpdateConnectedLineTask(this, sourceSession, connectedLine, mLogger));
+
+
+        // Forwards the ConnectedLine information to the other sessions in the bridge.
+        //  - Applies forwarding hooks to the cached ConnectedLine info before forwarding.
+        tasks.push_back(new ForwardConnectedLineTask(this, sourceSession, mLogger));
+
+        ExecutorPtr runner(new Executor(tasks, mLogger));
+        runner->start();
+    }
+    catch (const std::exception e)
+    {
+        mLogger(Debug) << FUNLOG << " : " << e.what();
+    }
+}
+
+/** 
+ * Process an updated Redirections record from a session. 
+ */
+void BridgeImpl::updateRedirections(const SessionWrapperPtr& sourceSession, const RedirectionsPtr& redirections)
+{
+    try
+    {
+        QueuedTasks tasks;
+
+        // Forwards the Redirections information to the other sessions in the bridge.
+        // Applies forwarding hooks to the Redirecrting info before forwarding.
+        tasks.push_back(new ForwardRedirectionsUpdatedTask(this, sourceSession, redirections, mLogger));
+        ExecutorPtr runner(new Executor(tasks, mLogger));
+        runner->start();
+    }
+    catch (const std::exception e)
+    {
+        mLogger(Debug) << FUNLOG << " : " << e.what();
+    }
+}
+
 void BridgeImpl::addSessions_async(const AMD_Bridge_addSessionsPtr& callback, const SessionSeq& sessions,
         const Ice::Current&)
 {
@@ -1319,12 +1643,14 @@ IceUtil::Handle<AsteriskSCF::BridgeService::BridgeServant>
 AsteriskSCF::BridgeService::BridgeServant::create(const string& name, const Ice::ObjectAdapterPtr& objectAdapter,
         const vector<BridgeListenerPrx>& listeners,
         const AsteriskSCF::BridgeService::BridgeListenerMgrPtr& listenerMgr,
+        const AsteriskSCF::Replication::BridgeService::V1::PartyIdHooksPtr& partyIdHooks,
         const ReplicatorSmartPrx& replicator,
         const Logger& logger)
 {
     BridgeStateItemPtr state(new AsteriskSCF::Replication::BridgeService::V1::BridgeStateItem);
     state->runningState = Running;
     state->serial = SerialCounterStart;
+    state->partyIdHookSet = partyIdHooks;
     //
     // TODO: "replicate" is the only replication policy currently supported by the bridge service.
     // In the future it may be possible for the bridge replica to reconstruct its media operations
diff --git a/src/BridgeImpl.h b/src/BridgeImpl.h
index 35b311f..d2a3fb3 100644
--- a/src/BridgeImpl.h
+++ b/src/BridgeImpl.h
@@ -16,8 +16,10 @@
 #pragma once
 
 #include <AsteriskSCF/SessionCommunications/SessionCommunicationsIf.h>
+#include <AsteriskSCF/Replication/BridgeService/BridgeReplicatorIf.h>
 #include <boost/thread/shared_mutex.hpp>
 #include <vector>
+#include "BridgePartyIdExtensionPoint.h"
 #include "BridgeReplicatorIf.h"
 #include "BridgeListenerMgr.h"
 #include "BridgeServiceConfig.h"
@@ -142,6 +144,7 @@ public:
             const Ice::ObjectAdapterPtr& objectAdapter,
             const std::vector<AsteriskSCF::SessionCommunications::V1::BridgeListenerPrx>& listeners,
             const AsteriskSCF::BridgeService::BridgeListenerMgrPtr& listenerMgr,
+            const AsteriskSCF::Replication::BridgeService::V1::PartyIdHooksPtr& partyIdHooks,
             const ReplicatorSmartPrx& replicator, 
             const AsteriskSCF::System::Logging::Logger& logger);
 
diff --git a/src/BridgeManagerImpl.cpp b/src/BridgeManagerImpl.cpp
index d8a343d..48acd21 100644
--- a/src/BridgeManagerImpl.cpp
+++ b/src/BridgeManagerImpl.cpp
@@ -78,7 +78,9 @@ class BridgeManagerImpl : public BridgeManagerServant
 {
 public:
 
-    BridgeManagerImpl(const Ice::ObjectAdapterPtr& adapter, const string& name,
+    BridgeManagerImpl(const Ice::ObjectAdapterPtr& adapter, 
+            const string& name,
+            const BridgePartyIdExtensionPointPtr& partyIdExtensionPoint,
             const BridgeReplicationContextPtr& replicationContext, const Logging::Logger& logger);
     ~BridgeManagerImpl();
 
@@ -127,6 +129,7 @@ private:
 
     boost::shared_mutex mLock;
     string mName;
+    BridgePartyIdExtensionPointPtr mPartyIdExtensionPoint;
     vector<BridgeInfo> mBridges;
     Ice::ObjectAdapterPtr mAdapter;
     BridgeReplicationContextPtr mReplicationContext;
@@ -148,13 +151,17 @@ private:
 
 typedef IceUtil::Handle<BridgeManagerImpl> BridgeManagerImplPtr;
 
-BridgeManagerImpl::BridgeManagerImpl(const Ice::ObjectAdapterPtr& adapter, const string& name, const BridgeReplicationContextPtr& replicationContext,
-        const Logger& logger) :
-    mName(name),
-    mAdapter(adapter),
-    mReplicationContext(replicationContext), 
-    mLogger(logger),
-    mState(new BridgeManagerStateItem)
+BridgeManagerImpl::BridgeManagerImpl(const Ice::ObjectAdapterPtr& adapter, 
+    const string& name, 
+    const BridgePartyIdExtensionPointPtr& partyIdExtensionPoint,
+    const BridgeReplicationContextPtr& replicationContext,
+    const Logger& logger) :
+        mName(name),
+        mPartyIdExtensionPoint(partyIdExtensionPoint),
+        mAdapter(adapter),
+        mReplicationContext(replicationContext), 
+        mLogger(logger),
+        mState(new BridgeManagerStateItem)
 {
     mLogger(Info) << "Created AsteriskSCF Session-Oriented Bridge Manager." ;
     mListeners = new BridgeManagerListenerMgr(mAdapter->getCommunicator(), mName, mSourceProxy);
@@ -275,7 +282,8 @@ void BridgeManagerImpl::createBridge_async(const AMD_BridgeManager_createBridgeP
         // initial sessions, etc that may have been defined or added as part of the createBridge
         // call or the bridge creation hooks.
         //
-        BridgeServantPtr bridge = BridgeServant::create(stringId, mAdapter, listeners, mgr, mReplicationContext->getReplicator(), mLogger);
+        BridgeServantPtr bridge = BridgeServant::create(stringId, mAdapter, listeners, mgr, 
+           mPartyIdExtensionPoint->getHooks(), mReplicationContext->getReplicator(), mLogger);
 
         Ice::ObjectPrx obj = mAdapter->add(bridge, id);
 
@@ -464,6 +472,7 @@ BridgeManagerStateItemPtr BridgeManagerImpl::getState()
     //
     BridgeManagerStateItemPtr result(new BridgeManagerStateItem(*mState));
     result->listeners = mListeners->getListeners();
+    result->partyIdExtensionPointHooks = mPartyIdExtensionPoint->getHooks();
     return result;
 }
 
@@ -477,6 +486,8 @@ void BridgeManagerImpl::updateState(const BridgeManagerStateItemPtr& state)
     // safer to take the added cost of the copy.
     //
     *mState = *state;
+
+    mPartyIdExtensionPoint->replaceHooks(state->partyIdExtensionPointHooks);
 }
 
 vector<BridgeServantPtr> BridgeManagerImpl::getBridges()
@@ -534,7 +545,9 @@ void BridgeManagerImpl::createBridgeReplica(const BridgeStateItemPtr& state)
     BridgePrx prx(BridgePrx::uncheckedCast(mAdapter->createProxy(id)));
     BridgeListenerMgrPtr mgr(new BridgeListenerMgr(mAdapter->getCommunicator(), state->bridgeId, prx));
 
-    BridgeServantPtr bridge = BridgeServant::create(mAdapter, mgr, mReplicationContext->getReplicator(), mLogger, state);
+
+    BridgeServantPtr bridge = BridgeServant::create(mAdapter, mgr, 
+        mReplicationContext->getReplicator(), mLogger, state);
     Ice::ObjectPrx obj = mAdapter->add(bridge, id);
 
     mLogger(Info) << ": creating bridge replica " << obj->ice_toString() << "." ;
@@ -617,9 +630,11 @@ void BridgeManagerImpl::update()
 } // End of anonymous namespace
 
 BridgeManagerServantPtr 
-AsteriskSCF::BridgeService::createBridgeManager(const Ice::ObjectAdapterPtr& adapter, const string& name,
-        const BridgeReplicationContextPtr& replicationContext,
-        const Logger& logger)
+AsteriskSCF::BridgeService::createBridgeManager(const Ice::ObjectAdapterPtr& adapter, 
+    const string& name,
+    const BridgePartyIdExtensionPointPtr& partyIdExtensionPoint,
+    const BridgeReplicationContextPtr& replicationContext,
+    const Logger& logger)
 {
-    return new BridgeManagerImpl(adapter, name, replicationContext, logger);
+    return new BridgeManagerImpl(adapter, name, partyIdExtensionPoint, replicationContext, logger);
 }
diff --git a/src/BridgeManagerImpl.h b/src/BridgeManagerImpl.h
index 163d5df..b1c4cc9 100644
--- a/src/BridgeManagerImpl.h
+++ b/src/BridgeManagerImpl.h
@@ -67,6 +67,10 @@ typedef IceUtil::Handle<BridgeManagerServant> BridgeManagerServantPtr;
  *
  * @param adapter The Ice object adapter for the BridgeManager all of the servants it will create.
  *
+ *
+ * @param partyIdExtensionPoint Object that manages the hooks that have been added to this component for
+ * modifying Party Id information.
+ *
  * @param name A name for this servant. This will be used to construct the new BridgeManager object's Ice::Identity. 
  *             It is used to construct relative object ids for all objects that the bridge manager creates.
  *
@@ -74,7 +78,9 @@ typedef IceUtil::Handle<BridgeManagerServant> BridgeManagerServantPtr;
  *
  **/
 BridgeManagerServantPtr createBridgeManager(const Ice::ObjectAdapterPtr& adapter,
-        const std::string& name, const BridgeReplicationContextPtr& replicationContext,
+        const std::string& name, 
+        const BridgePartyIdExtensionPointPtr& partyIdExtensionPoint,
+        const BridgeReplicationContextPtr& replicationContext,
         const AsteriskSCF::System::Logging::Logger& logger);
 
 };
diff --git a/src/BridgePartyIdExtensionPoint.cpp b/src/BridgePartyIdExtensionPoint.cpp
... 2582 lines suppressed ...


-- 
asterisk-scf/integration/bridging.git



More information about the asterisk-scf-commits mailing list