[asterisk-scf-commits] asterisk-scf/release/bridging.git branch "master" updated.
Commits to the Asterisk SCF project code repositories
asterisk-scf-commits at lists.digium.com
Thu May 19 20:23:08 CDT 2011
branch "master" has been updated
via ba502f18be3aa445072142f9bbca16efb61c4df0 (commit)
from 41a1d26e130b1b0b00e8367bd3643eb8a0143758 (commit)
Summary of changes:
src/BridgeImpl.cpp | 3 +-
src/SessionListener.cpp | 47 +++++++++++++++++++----
src/SessionListener.h | 21 ++++++++++-
src/SessionWrapper.cpp | 28 ++++++++++----
src/SessionWrapper.h | 2 +-
test/TestBridging.cpp | 94 +++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 176 insertions(+), 19 deletions(-)
- Log -----------------------------------------------------------------
commit ba502f18be3aa445072142f9bbca16efb61c4df0
Author: Brent Eagles <beagles at digium.com>
Date: Thu May 19 22:50:50 2011 -0230
- Add proxies to the session listener so it can decide to call shutdown on the
bridge if the session count is going to drop below 2 when it receives a stopped
indication. Added test for same.
- Also modified the RemoveBridge task to "swallow" the NotBridged exception as
it could very well have been a result of multiple shutdown/removals of a given
session at the same time.
diff --git a/src/BridgeImpl.cpp b/src/BridgeImpl.cpp
index 0ce1947..15dd93a 100755
--- a/src/BridgeImpl.cpp
+++ b/src/BridgeImpl.cpp
@@ -140,7 +140,7 @@ private:
//
// The bridge's callback implementation for the sessions that get added to it.
//
- SessionListenerPtr mSessionListener;
+ BridgeSessionListenerPtr mSessionListener;
SessionListenerPrx mSessionListenerPrx;
//
@@ -853,6 +853,7 @@ void BridgeImpl::activate(const BridgePrx& proxy)
SessionListenerPrx::uncheckedCast(
mObjAdapter->add(mSessionListener, mObjAdapter->getCommunicator()->stringToIdentity(listenerId))
);
+ mSessionListener->onActivate(mPrx, mSessionListenerPrx);
ReplicatedStateItemSeq initialUpdates;
BridgeStateItemPtr update = createUpdate();
diff --git a/src/SessionListener.cpp b/src/SessionListener.cpp
index ec8989a..86a2fca 100644
--- a/src/SessionListener.cpp
+++ b/src/SessionListener.cpp
@@ -33,7 +33,7 @@ namespace
// For events result in distribution to the bridge sessions, we copy the current sessions and
// run the calls from the listener itself.
//
-class SessionListenerImpl : public SessionListener
+class SessionListenerImpl : public BridgeSessionListener
{
public:
SessionListenerImpl(const SessionCollectionPtr& b, const Logger& logger) :
@@ -43,7 +43,7 @@ public:
}
void indicated(const AsteriskSCF::SessionCommunications::V1::SessionPrx& source,
- const AsteriskSCF::SessionCommunications::V1::IndicationPtr& indication, const Ice::Current& current)
+ const AsteriskSCF::SessionCommunications::V1::IndicationPtr& indication, const Ice::Current&)
{
AsteriskSCF::SessionCommunications::V1::ConnectedIndicationPtr connected;
AsteriskSCF::SessionCommunications::V1::RingingIndicationPtr ringing;
@@ -111,27 +111,58 @@ public:
return;
}
- //
- // We don't actually have the proxy for this object, but we can create one on the fly.
- //
- SessionListenerPrx listenerPrx = SessionListenerPrx::uncheckedCast(current.adapter->createProxy(current.id));
+ //
+ // This returns only the active sessions.
+ //
+ SessionSeq currentSessions = mSessions->getSessionSeq();
//
// Shutdown is handled asynchronously, so there won't be any exceptions that need to be caught here.
// A null response code pointer will prevent the stop indication from being sent back to this session.
//
- session->shutdown(listenerPrx, ResponseCodePtr());
+ session->shutdown(mListenerPrx, ResponseCodePtr());
+
+ //
+ // Ideally, we'd wait for an affirmative response from the session being removed from the bridge
+ // before doing this next part.
+ //
+ if (mBridgePrx)
+ {
+ try
+ {
+ //
+ // TODO: Should be determined by policy. 2 is the proper upper limit because
+ // the session in question will not have been removed from the bridge yet.
+ //
+ if (currentSessions.size() <= 2)
+ {
+ mBridgePrx->shutdown();
+ }
+ }
+ catch (const Ice::Exception& ex)
+ {
+ mLogger(Error) << "Unexpected exception when initiating auto shutdown";
+ }
+ }
}
}
+ void onActivate(const BridgePrx& bridgePrx, const SessionListenerPrx& listenerPrx)
+ {
+ mBridgePrx = bridgePrx;
+ mListenerPrx = listenerPrx;
+ }
+
private:
SessionCollectionPtr mSessions;
Logger mLogger;
+ BridgePrx mBridgePrx;
+ SessionListenerPrx mListenerPrx;
};
}
-SessionListenerPtr AsteriskSCF::BridgeService::createSessionListener(const SessionCollectionPtr& sessions,
+BridgeSessionListenerPtr AsteriskSCF::BridgeService::createSessionListener(const SessionCollectionPtr& sessions,
const Logger& logger)
{
return new SessionListenerImpl(sessions, logger);
diff --git a/src/SessionListener.h b/src/SessionListener.h
index 0d65892..04f087d 100644
--- a/src/SessionListener.h
+++ b/src/SessionListener.h
@@ -30,7 +30,26 @@ class Logger;
namespace BridgeService
{
-AsteriskSCF::SessionCommunications::V1::SessionListenerPtr createSessionListener(const SessionCollectionPtr& sessions,
+//
+// TODO: Should go in it's own header file.
+//
+class BridgeSessionListener: public virtual AsteriskSCF::SessionCommunications::V1::SessionListener
+{
+public:
+ virtual ~BridgeSessionListener() {}
+
+ /**
+ *
+ * Called ONCE when the servant is added to the object adapter!
+ *
+ **/
+ virtual void onActivate(const AsteriskSCF::SessionCommunications::V1::BridgePrx& bridgePrx,
+ const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listenerPrx) =0;
+};
+
+typedef IceUtil::Handle<BridgeSessionListener> BridgeSessionListenerPtr;
+
+BridgeSessionListenerPtr createSessionListener(const SessionCollectionPtr& sessions,
const AsteriskSCF::System::Logging::Logger& logger);
diff --git a/src/SessionWrapper.cpp b/src/SessionWrapper.cpp
index ac8234b..d514e3b 100644
--- a/src/SessionWrapper.cpp
+++ b/src/SessionWrapper.cpp
@@ -122,12 +122,27 @@ protected:
mListener->succeeded();
}
- void failed(const Ice::Exception&)
+ void failed(const Ice::Exception& ex)
{
- //
- // TODO: Log exception.
- //
- mListener->failed();
+
+ try
+ {
+ ex.ice_throw();
+ }
+ catch (const NotBridged&)
+ {
+ //
+ // This is most likely ok, it just means removeBridge was called
+ // twice.
+ //
+ }
+ catch (...)
+ {
+ //
+ // TODO: Log exception.
+ //
+ mListener->failed();
+ }
}
void failImpl()
@@ -296,9 +311,6 @@ QueuedTasks createShutdownTasks(const SessionWrapperPtr& session, const SessionL
QueuedTasks tasks;
tasks.push_back(new SetStateTask(session, Disconnected));
tasks.push_back(new RemoveBridgeTask(session, listener));
- //
- // TODO: this should really go through a different interface.
- //
if (code)
{
tasks.push_back(new SessionStopTask(session, code));
diff --git a/src/SessionWrapper.h b/src/SessionWrapper.h
index b955280..0c98112 100644
--- a/src/SessionWrapper.h
+++ b/src/SessionWrapper.h
@@ -122,7 +122,7 @@ public:
void setup();
void shutdown(const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listener,
- const AsteriskSCF::SessionCommunications::V1::ResponseCodePtr& code);
+ const AsteriskSCF::SessionCommunications::V1::ResponseCodePtr& code);
//
// TODO: Refactor so these methods don't need to be exposed.
diff --git a/test/TestBridging.cpp b/test/TestBridging.cpp
index 5407259..b5546db 100644
--- a/test/TestBridging.cpp
+++ b/test/TestBridging.cpp
@@ -451,6 +451,98 @@ public:
}
};
+ void testAutoShutdown()
+ {
+ 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"));
+
+ bridge->addSessions(sessions);
+ //
+ // Check for regression where the bridge was calling start on sessions.
+ //
+ channel.commands()->getlog(idA, log);
+ BOOST_CHECK(!find(log, "start"));
+ channel.commands()->getlog(idB, log);
+ BOOST_CHECK(!find(log, "start"));
+
+ a->start();
+ b->start();
+
+ channel.commands()->getlog(idA, log);
+ BOOST_CHECK(find(log, "start"));
+ channel.commands()->getlog(idB, log);
+ BOOST_CHECK(find(log, "start"));
+
+ //
+ // Should result in a media hookup!
+ //
+ channel.commands()->answer(idA);
+ channel.commands()->answer(idB);
+
+ IceUtil::ThreadControl::sleep(IceUtil::Time::seconds(2));
+ channel.commands()->hangup(idA);
+ IceUtil::ThreadControl::sleep(IceUtil::Time::seconds(2));
+
+ BOOST_CHECK(servant->createCalls() == 1);
+
+ channel.commands()->getlog(idB, log);
+ bool findStop = find(log, "stop");
+ if (!findStop)
+ {
+ dumplog(log);
+ }
+ BOOST_CHECK(findStop);
+ }
+ 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 bridgeDefaultListenerTest()
{
try
@@ -772,6 +864,8 @@ bool init_unit_test()
framework::master_test_suite().
add(BOOST_TEST_CASE(boost::bind(&BridgeTester::simpleBridgingTest, bridgeTester)));
framework::master_test_suite().
+ add(BOOST_TEST_CASE(boost::bind(&BridgeTester::testAutoShutdown, bridgeTester)));
+ framework::master_test_suite().
add(BOOST_TEST_CASE(boost::bind(&BridgeTester::bridgeDefaultListenerTest, bridgeTester)));
framework::master_test_suite().
add(BOOST_TEST_CASE(boost::bind(&BridgeTester::bridgeManagerListeners, bridgeTester)));
-----------------------------------------------------------------------
--
asterisk-scf/release/bridging.git
More information about the asterisk-scf-commits
mailing list