[asterisk-scf-commits] asterisk-scf/integration/routing.git branch "transfer" updated.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Tue Oct 12 19:26:04 CDT 2010


branch "transfer" has been updated
       via  a5e884534bef416a6a556b3efdff62c35b560aea (commit)
      from  942efe88a38dbe7c6631ef93e7fb5aa2a7d83443 (commit)

Summary of changes:
 src/SessionRouter.cpp |   99 ++++++++++++++++++++++++++++--------------------
 src/SessionRouter.h   |   12 +++---
 test/MockBridge.cpp   |   12 +++++-
 test/MockBridge.h     |    8 ++--
 test/SharedTestData.h |    3 +-
 test/TestRouting.cpp  |   54 +++++++++++++++++++++++++-
 6 files changed, 132 insertions(+), 56 deletions(-)


- Log -----------------------------------------------------------------
commit a5e884534bef416a6a556b3efdff62c35b560aea
Author: Ken Hunt <ken.hunt at digium.com>
Date:   Tue Oct 12 19:23:41 2010 -0500

    Refactoring call transfer changes based on telecon.
    replaceSessionWithDestination / replaceSessionWithSession are now
    connectBridgedSessionsWithDestination / connectBridgedSessions.

diff --git a/src/SessionRouter.cpp b/src/SessionRouter.cpp
index f7a8f46..7d3aed5 100644
--- a/src/SessionRouter.cpp
+++ b/src/SessionRouter.cpp
@@ -351,14 +351,14 @@ void SessionRouter::routeSession(const AsteriskSCF::SessionCommunications::V1::S
 }
 
 /**
-* Execute the routing functionality for the given session. The given session
-* will be bridged with the destination if it is successfully routed. 
-*   @param source The session initiating the routing event. 
-*   @param destination The address or id of the destination to be routed. 
-*/
-void SessionRouter::replaceSessionWithDestination(const ::AsteriskSCF::SessionCommunications::V1::SessionPrx& sessionToReplace, 
-                                 const ::std::string& destination,
-                                 const Ice::Current& current)
+ * Replace one session in a Bridge with a new
+ * session routable by the destination param. 
+ *   @param source The session initiating the routing event. 
+ *   @param destination The address or id of the destination to be routed. 
+ */
+void SessionRouter::connectBridgedSessionsWithDestination(const SessionPrx& sessionToReplace, 
+                                                          const ::std::string& destination,
+                                                          const Ice::Current& current)
 {
     BridgePrx bridge(0);
     try
@@ -438,7 +438,9 @@ void SessionRouter::replaceSessionWithDestination(const ::AsteriskSCF::SessionCo
     // Modify the bridge
     try
     {
-        bridge->replaceSession(destSession, sessionToReplace);
+        SessionSeq seq;
+        seq.push_back(destSession);
+        bridge->replaceSession(sessionToReplace, seq);
     }
     catch (const Ice::Exception &e)
     {
@@ -452,27 +454,35 @@ void SessionRouter::replaceSessionWithDestination(const ::AsteriskSCF::SessionCo
 
     mImpl->forwardStart(listener, source);
 
+    sessionToReplace->stop(new ResponseCode(16)); // Magic number! We need our own value mapping of isdn codes
+
     // We're done with the listener.
     mImpl->deleteListener(listener);
 }
 
 /**
-* Replace a session in a bridge with another session. If the newSession is already participating in a Bridge,
-* it will be removed from it's current bridge prior to be used as a replacement. 
-*   @param sessionToReplace The session to be replaced in a bridge. The affected Bridge interface is 
-*    obtained via an accessor on this interface. 
-*   @param newSession The session to be used as a replacement for the specified session.
-*/
-void SessionRouter::replaceSessionWithSession(const ::AsteriskSCF::SessionCommunications::V1::SessionPrx& sessionToReplace, 
-                             const ::AsteriskSCF::SessionCommunications::V1::SessionPrx& newSession,
-                             const Ice::Current&)
+ * Replace one session in a Bridge with sessions from another bridge. 
+ * No routing is actually performed. This operation exists here for consistency,
+ * since connectBridgedSessionsWithDestination(...) is implemented by this interface. 
+ * @param sessionToReplace The session that is to be replaced in a 
+ *   bridge. The bridge obejct associated with this session will survive, and
+ *   all sessions bridged to this session will be kept in the bridge. 
+ * @param bridgedSession This session is assumed to be bridged to the sessions
+ *   that are to be moved to another bridge. The bridgedSession itself will not
+ *   be connected to the other bridge. The sessions being moved will be removed from
+ *   their current bridge before being added to the bridge currenltly attached to 
+ *   sessionToReplace. 
+ */
+void SessionRouter::connectBridgedSessions(const SessionPrx& sessionToReplace, 
+                                           const SessionPrx& bridgedSession,
+                                           const Ice::Current&)
 {
 
-    // Get the bridge being modified.
-    BridgePrx newBridge(0);
+    // Get the bridge being merged into.
+    BridgePrx mergeBridge(0);
     try
     {
-        newBridge = sessionToReplace->getBridge();
+        mergeBridge = sessionToReplace->getBridge();
     }
     catch(const NotBridged& e)
     {
@@ -480,10 +490,10 @@ void SessionRouter::replaceSessionWithSession(const ::AsteriskSCF::SessionCommun
        throw e; // rethrow
     }
 
-    SessionSeq seq;
+    SessionSeq preserveSessions;
     try
     {
-        seq = newBridge->listSessions();
+        preserveSessions = mergeBridge->listSessions();
     }
     catch(const Ice::Exception &e)
     {
@@ -494,14 +504,14 @@ void SessionRouter::replaceSessionWithSession(const ::AsteriskSCF::SessionCommun
     // Add a listener to the session not being replaced to handle early termination.
     SessionListenerImplPtr listener(0);
     SessionPrx source(0);
-    for(SessionSeq::iterator s = seq.begin(); s !=seq.end(); ++s)
+    for(SessionSeq::iterator s = preserveSessions.begin(); s !=preserveSessions.end(); ++s)
     {
         if (sessionToReplace->ice_getIdentity() != (*s)->ice_getIdentity())
         {
             if (listener == 0)
             {
                 source = (*s);
-                listener = mImpl->createListener(source); // Only listening to the session NOT being transferred.
+                listener = mImpl->createListener(source); // Only listening to sessions NOT being replaced.
             }
             else
             { 
@@ -510,25 +520,40 @@ void SessionRouter::replaceSessionWithSession(const ::AsteriskSCF::SessionCommun
         }
     }
 
-    // Get the bridge for the session being moved. 
+    // Get the bridge for the sessions being moved. 
     BridgePrx oldBridge(0);
     try
     {
-        oldBridge = newSession->getBridge();
+        oldBridge = bridgedSession->getBridge();
     }
     catch(const NotBridged&)
     {
-        lg(Warning) << "Unable to get bridge for the newSession in replaceSessionWithSession(). " ;
+        lg(Warning) << "Unable to get bridge for the bridgedSession in replaceSessionWithSession(). " ;
+    }
+
+    // Check for early termination by the source.
+    if (listener->isTerminated())
+    {
+        mImpl->deleteListener(listener);
+        lg(Notice) << "Source ended session before transfer in replaceSessionWithSession(). " ;
+        throw SourceTerminatedPreBridgingException(source->getEndpoint()->getId());
     }
 
+    SessionSeq migratingSessions;
     if (oldBridge != 0)
     {
         try
         {
-            // Remove the session being moved from it's old bridge. 
-            SessionSeq sessions;
-            sessions.push_back(newSession);
-            oldBridge->removeSessions(sessions);
+            // Remove the sessions being moved from their old bridge. 
+            SessionSeq allSessions = oldBridge->listSessions();
+            for(SessionSeq::iterator s = allSessions.begin(); s != allSessions.end(); ++s)
+            {
+                if ((*s) != bridgedSession)
+                {
+                    migratingSessions.push_back(*s);
+                }
+            }
+            oldBridge->removeSessions(migratingSessions);
         }
         catch(const Ice::Exception&)
         {
@@ -537,20 +562,12 @@ void SessionRouter::replaceSessionWithSession(const ::AsteriskSCF::SessionCommun
         }
     }
 
-    // Check for early termination by the source.
-    if (listener->isTerminated())
-    {
-        mImpl->deleteListener(listener);
-        lg(Notice) << "Source ended session before transfer in replaceSessionWithSession(). " ;
-        throw SourceTerminatedPreBridgingException(source->getEndpoint()->getId());
-    }
-
     // Now replace the sessions. 
     // TBD... make order of newSession and sessionToBeReplaced consistent 
     // between bridge and this operation. 
     try
     {
-        newBridge->replaceSession(newSession, sessionToReplace);
+        mergeBridge->replaceSession(sessionToReplace, migratingSessions);
     }
     catch(const Ice::Exception& e)
     {
diff --git a/src/SessionRouter.h b/src/SessionRouter.h
index f82c2a5..99f3c9e 100644
--- a/src/SessionRouter.h
+++ b/src/SessionRouter.h
@@ -51,9 +51,9 @@ public:
      *    obtained via an accessor on this interface. 
      *   @param destination The address or id of a destination to be used as a replacement for the specified session.
      */
-    void replaceSessionWithDestination(const ::AsteriskSCF::SessionCommunications::V1::SessionPrx& sessionToReplace, 
-                                       const ::std::string& destination,
-                                       const Ice::Current&);
+    void connectBridgedSessionsWithDestination(const ::AsteriskSCF::SessionCommunications::V1::SessionPrx& sessionToReplace, 
+                                               const ::std::string& destination,
+                                               const Ice::Current&);
 
     /**
      * Replace a session in a bridge with another session. If the newSession is already participating in a Bridge,
@@ -62,9 +62,9 @@ public:
      *    obtained via an accessor on this interface. 
      *   @param newSession The session to be used as a replacement for the specified session.
      */
-    void replaceSessionWithSession(const ::AsteriskSCF::SessionCommunications::V1::SessionPrx& sessionToReplace, 
-                                   const ::AsteriskSCF::SessionCommunications::V1::SessionPrx& newSession,
-                                   const Ice::Current&);
+    void connectBridgedSessions(const ::AsteriskSCF::SessionCommunications::V1::SessionPrx& sessionToReplace, 
+                                const ::AsteriskSCF::SessionCommunications::V1::SessionPrx& bridgedSession,
+                                const Ice::Current&);
 
 private: 
     boost::shared_ptr<SessionRouterPriv> mImpl;
diff --git a/test/MockBridge.cpp b/test/MockBridge.cpp
index 2ef893d..e804aa0 100644
--- a/test/MockBridge.cpp
+++ b/test/MockBridge.cpp
@@ -87,10 +87,20 @@ void MockBridge::addSessions(const SessionSeq& newSessions, const Ice::Current&)
    mSessions.insert( mSessions.end(), newSessions.begin(), newSessions.end());
 }
 
+void MockBridge::removeListener(const AsteriskSCF::SessionCommunications::V1::BridgeListenerPrx&, const Ice::Current& )
+{
+}
+
+void MockBridge::replaceSession(const AsteriskSCF::SessionCommunications::V1::SessionPrx& sessionToReplace,
+  const AsteriskSCF::SessionCommunications::V1::SessionSeq& newSessions,
+  const Ice::Current&)
+{
+    SharedTestData::instance.mSessionReplaced = true;
+}
 
 void MockBridge::connected(const AsteriskSCF::SessionCommunications::V1::SessionPrx& session)
 {
-   SharedTestData::instance.connected = true;
+    SharedTestData::instance.mBridgeConnected = true;
 }
 
 } // RoutingTest
diff --git a/test/MockBridge.h b/test/MockBridge.h
index 17aa727..4b98987 100644
--- a/test/MockBridge.h
+++ b/test/MockBridge.h
@@ -36,11 +36,11 @@ public:
 
     void shutdown(const Ice::Current&) {}
     void addListener(const AsteriskSCF::SessionCommunications::V1::BridgeListenerPrx&, const Ice::Current& ) {}
-    void removeListener(const AsteriskSCF::SessionCommunications::V1::BridgeListenerPrx&, const Ice::Current& ) {}
+    void removeListener(const AsteriskSCF::SessionCommunications::V1::BridgeListenerPrx&, const Ice::Current& );
 
-    void replaceSession(const AsteriskSCF::SessionCommunications::V1::SessionPrx& newSession,
-      const AsteriskSCF::SessionCommunications::V1::SessionPrx& oldSession,
-      const Ice::Current&) {}
+    void replaceSession(const AsteriskSCF::SessionCommunications::V1::SessionPrx& sessionToReplace,
+      const AsteriskSCF::SessionCommunications::V1::SessionSeq& newSessions,
+      const Ice::Current&);
 
     void connected(const AsteriskSCF::SessionCommunications::V1::SessionPrx& session);
 
diff --git a/test/SharedTestData.h b/test/SharedTestData.h
index eeecab7..2a22e1c 100644
--- a/test/SharedTestData.h
+++ b/test/SharedTestData.h
@@ -50,7 +50,8 @@ struct SharedTestData
 
     MockBridgeManagerPtr bridgeManager;
 
-    bool connected;
+    bool mBridgeConnected;
+    bool mSessionReplaced;
 };
 
 } // RoutingTest
diff --git a/test/TestRouting.cpp b/test/TestRouting.cpp
index cd9fa21..63b072d 100644
--- a/test/TestRouting.cpp
+++ b/test/TestRouting.cpp
@@ -203,11 +203,12 @@ struct GlobalIceFixture
         SharedTestData::instance.endpointLocator->addEndpoint("101");
         SharedTestData::instance.endpointLocator->addEndpoint("102");
         SharedTestData::instance.endpointLocator->addEndpoint("103");
+        SharedTestData::instance.endpointLocator->addEndpoint("104");
 
         // Initialize the regular expressions for the ids that this channel will support.
         // Use two strings just for kicks. 
         SharedTestData::instance.regExIds.push_back("101");
-        SharedTestData::instance.regExIds.push_back("10[23]");  // 102 or 103
+        SharedTestData::instance.regExIds.push_back("10[234]");  // 102, 103 or 104
     }
 
     ~GlobalIceFixture()
@@ -398,12 +399,59 @@ BOOST_FIXTURE_TEST_CASE(RouteSession, PerTestFixture)
         SessionPrx session = session101Endpoint->createSession("102", 0, Ice::Current());
         BOOST_CHECK(session != 0);
 
-        SharedTestData::instance.connected = false;
+        SharedTestData::instance.mBridgeConnected = false;
 
         BOOST_TEST_MESSAGE("Routing the session...");
         SharedTestData::instance.sessionRouter->routeSession(session, "102");
 
-        BOOST_CHECK(SharedTestData::instance.connected);
+        BOOST_CHECK(SharedTestData::instance.mBridgeConnected);
+    }
+    catch(const IceUtil::Exception &ie)
+    {
+        bool IceException(false);
+        string msg = "Exception routing session:";
+        msg += ie.what();
+        BOOST_TEST_MESSAGE(msg);
+        BOOST_CHECK(IceException);
+    }
+    catch (...)
+    {
+        bool unknownException(false);
+        BOOST_TEST_MESSAGE("Exception routing session.");
+        BOOST_CHECK(unknownException);
+    }
+}
+
+/** 
+ * This tests if we can support blind transfer. 
+ */
+BOOST_FIXTURE_TEST_CASE(BlindTransfer, PerTestFixture)
+{
+    try
+    {
+        BOOST_TEST_MESSAGE("Local lookup of an endpoint...");
+
+        // Get our local 101 endpoint
+        MockSessionEndpointPtr session101Endpoint = SharedTestData::instance.endpointLocator->localLookup("101");
+
+        BOOST_TEST_MESSAGE("Creating a session on our test endpoint...");
+        SessionPrx session = session101Endpoint->createSession("102", 0, Ice::Current());
+        BOOST_CHECK(session != 0);
+
+        SharedTestData::instance.mBridgeConnected = false;
+        SharedTestData::instance.mSessionReplaced = false;
+
+        BOOST_TEST_MESSAGE("Routing the session...");
+        SharedTestData::instance.sessionRouter->routeSession(session, "102");
+
+        BridgePrx bridge = session->getBridge();
+        BOOST_CHECK(SharedTestData::instance.mBridgeConnected);
+
+        // Now transfer to a new extension. 
+ // TBD...
+ //       SharedTestData::instance.sessionRouter->connectBridgedSessionsWithDestination(session, "103");
+
+ //       BOOST_CHECK(SharedTestData::instance.mSessionReplaced);
     }
     catch(const IceUtil::Exception &ie)
     {

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


-- 
asterisk-scf/integration/routing.git



More information about the asterisk-scf-commits mailing list