[asterisk-scf-commits] asterisk-scf/integration/sip.git branch "retry_deux" updated.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Fri Jan 20 13:59:41 CST 2012


branch "retry_deux" has been updated
       via  f7de9e3e3c9e447f89543e57e35a98857ff95e70 (commit)
      from  0d7330f79f2e697442a5b9498f71d84b39a2bacf (commit)

Summary of changes:
 src/PJSIPSessionModule.cpp |   59 +++++++++++++++++++++++++++-----
 src/SIPTransfer.cpp        |   81 +++++++++++++++++++++++++++++++++++++++----
 src/SIPTransfer.h          |   26 ++++++++++++++
 3 files changed, 149 insertions(+), 17 deletions(-)


- Log -----------------------------------------------------------------
commit f7de9e3e3c9e447f89543e57e35a98857ff95e70
Author: Ken Hunt <ken.hunt at digium.com>
Date:   Fri Jan 20 13:59:48 2012 -0600

    Adding additional retry logic for the other session router operations.

diff --git a/src/PJSIPSessionModule.cpp b/src/PJSIPSessionModule.cpp
index 754502e..1cd5ead 100644
--- a/src/PJSIPSessionModule.cpp
+++ b/src/PJSIPSessionModule.cpp
@@ -2028,7 +2028,12 @@ public:
             const std::string& contact,
             const AsteriskSCF::Discovery::SmartProxy<SessionRouterPrx>& router,
             const SIPSessionPtr& session)
-        : mInv(inv), mContact(contact), mRouter(router), mSession(session) { }
+        : mInv(inv), 
+          mContact(contact), 
+          mRouter(router), 
+          mSession(session),
+          mRetryPolicy(5, 500),
+          mOperationId(::IceUtil::generateUUID()) { }
 
 protected:
     SuspendableWorkResult initial(const SuspendableWorkListenerPtr&)
@@ -2037,14 +2042,8 @@ protected:
         {
             SuspendableWorkListenerPtr listener = 0;
             SIPAMICallbackPtr cb(new SIPAMICallback(listener, mSession, this, false, true));
-            Ice::CallbackPtr d = Ice::newCallback(cb, &SIPAMICallback::callback);
-            mRouter->begin_connectBridgedSessionsWithDestination(
-                    IceUtil::generateUUID(),
-                    mSession->getSessionProxy(),
-                    mContact,
-                    true,
-                    0,
-                    d);
+            SIPAMICallbackCookiePtr cookie = new SIPAMICallbackCookie(cb);
+            invokeOperation(cookie);
         }
         catch (const Ice::CommunicatorDestroyedException&)
         {
@@ -2053,6 +2052,24 @@ protected:
         return Complete;
     }
 
+    /**
+     * Invoke the operation. 
+     * @param cookie The cookie contains the SIPAMICallback object. Passed into the AMI operation so 
+     * that retry operations have access to the callback object. 
+     */
+    void invokeOperation(const SIPAMICallbackCookiePtr& cookie)
+    {
+        Ice::CallbackPtr d = Ice::newCallback(cookie->getSIPAMICallback(), &SIPAMICallback::callback);
+        mRouter->begin_connectBridgedSessionsWithDestination(
+            mOperationId,
+            mSession->getSessionProxy(),
+            mContact,
+            true,
+            0,
+            d,
+            cookie);
+    }
+
     SuspendableWorkResult calledBack(const Ice::AsyncResultPtr& asyncResult)
     {
         SessionRouterPrx router =
@@ -2066,6 +2083,28 @@ protected:
         {
             router->end_connectBridgedSessionsWithDestination(asyncResult);
         }
+        catch (const Ice::ConnectionLostException &cle)
+        {
+            // Assume a failover is occurring for the routing service. 
+            // This will block the WorkQueue's thread, but it's highly likely
+            // that the failover effects most of the other enqueued operations 
+            // anyway. 
+            if(mRetryPolicy.retry())
+            {
+                lg(Warning) << "HandleRedirection: Retrying connectBridgedSessionsWithDestination operation.";
+
+                // Retry the operation. 
+                invokeOperation(SIPAMICallbackCookiePtr::dynamicCast(asyncResult->getCookie()));
+            }
+            else
+            {
+                lg(Error) << "HandleRedirection: connectBridgedSessionsWithDestination failed "  << mRetryPolicy.getMaxRetries() << " retries." ;
+
+                op = PJSIP_REDIRECT_REJECT;
+                pjsip_inv_process_redirect(mInv, op, NULL);
+            }
+            return Complete;
+        }
         catch (const std::exception&)
         {
             op = PJSIP_REDIRECT_REJECT;
@@ -2080,6 +2119,8 @@ private:
     const std::string mContact;
     AsteriskSCF::Discovery::SmartProxy<SessionRouterPrx> mRouter;
     SIPSessionPtr mSession;
+    RetryPolicy mRetryPolicy;
+    std::string mOperationId;
 };
 
 pjsip_redirect_op PJSIPSessionModule::invOnRedirected(pjsip_inv_session* inv, const pjsip_uri* uri,
diff --git a/src/SIPTransfer.cpp b/src/SIPTransfer.cpp
index 2620727..0f0b06b 100644
--- a/src/SIPTransfer.cpp
+++ b/src/SIPTransfer.cpp
@@ -417,7 +417,9 @@ HandleReferOperation::HandleReferOperation(
     mReplicationContext(replicationContext),
     mModuleId(moduleId),
     mReferCSeq(tsx->cseq),
-    mBlindTransfer(false) {}
+    mBlindTransfer(false),
+    mOperationId(::IceUtil::generateUUID()),
+    mRetryPolicy(5, 500)  {}
 
 HandleReferOperation::~HandleReferOperation()
 {
@@ -484,20 +486,20 @@ SuspendableWorkResult HandleReferOperation::initial(const SuspendableWorkListene
         }
 
         PJSIPSessionModInfo *other_session_mod_info = (PJSIPSessionModInfo*)other_inv->mod_data[mModuleId];
-        SIPSessionPtr other_session = other_session_mod_info->getSessionPtr();
+        mOtherSession = other_session_mod_info->getSessionPtr();
 
         //Go ahead and send a 202 for the REFER. We can send a NOTIFY later to indicate if something
         //on the outbound leg went awry.
         pjsip_dlg_send_response(mInv->dlg, mTsx, mTdata);
         try
         {
-            std::string operationId = ::IceUtil::generateUUID();
             SIPAMICallbackPtr cb(new SIPAMICallback(workListener, mSession, this, false, true));
-            Ice::CallbackPtr d = Ice::newCallback(cb, &SIPAMICallback::callback);
+            SIPAMICallbackCookiePtr cookie = new SIPAMICallbackCookie(cb);
 
             lg(Debug) << "handleRefer() calling router connectBridgedSessions(). ";
 
-            mSessionRouter->begin_connectBridgedSessions(operationId, mSession->getSessionProxy(), other_session->getSessionProxy(), true, d);
+            invokeTransfer(cookie);
+
             pjsip_dlg_dec_lock(other_dlg);
             return Complete;
         }
@@ -518,11 +520,10 @@ SuspendableWorkResult HandleReferOperation::initial(const SuspendableWorkListene
         // Now that we have the target user we can pass this into routing and go on our marry way
         try
         {
-            std::string operationId = ::IceUtil::generateUUID();
             PJSIPSessionModInfo *session_mod_info = (PJSIPSessionModInfo*)mInv->mod_data[mModuleId];
             SIPSessionPtr session = session_mod_info->getSessionPtr();
             SIPAMICallbackPtr cb(new SIPAMICallback(workListener, mSession, this, false, true));
-            Ice::CallbackPtr d = Ice::newCallback(cb, &SIPAMICallback::callback);
+            SIPAMICallbackCookiePtr cookie = new SIPAMICallbackCookie(cb);
 
             lg(Debug) << "handleRefer() calling router connectBridgedSessionsWithDestination(). ";
             lg(Debug) << "Session to replace is with endpoint " << session->getEndpoint()->getName();
@@ -539,7 +540,8 @@ SuspendableWorkResult HandleReferOperation::initial(const SuspendableWorkListene
                 pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
             }
 
-            mSessionRouter->begin_connectBridgedSessionsWithDestination(operationId, session->getSessionProxy(), mTarget, true, mHook->getProxy(), d);
+            invokeBlindTransfer(cookie);
+
             return Complete;
         }
         catch (const Ice::CommunicatorDestroyedException &)
@@ -552,6 +554,32 @@ SuspendableWorkResult HandleReferOperation::initial(const SuspendableWorkListene
     }
 };
 
+/**
+ * Invoke a blind transfer operation. 
+ * @param cookie The cookie contains the SIPAMICallback object. Passed into the AMI operation so 
+ * that retry operations have access to the callback object. 
+ */
+void HandleReferOperation::invokeBlindTransfer(const SIPAMICallbackCookiePtr& cookie)
+{
+    Ice::CallbackPtr d = Ice::newCallback(cookie->getSIPAMICallback(), &SIPAMICallback::callback);
+
+    PJSIPSessionModInfo *session_mod_info = (PJSIPSessionModInfo*)mInv->mod_data[mModuleId];
+    SIPSessionPtr session = session_mod_info->getSessionPtr();
+
+    mSessionRouter->begin_connectBridgedSessionsWithDestination(mOperationId, session->getSessionProxy(), mTarget, true, mHook->getProxy(), d);
+}
+
+/**
+ * Invoke a transfer operation. 
+ * @param cookie The cookie contains the SIPAMICallback object. Passed into the AMI operation so 
+ * that retry operations have access to the callback object. 
+ */
+void HandleReferOperation::invokeTransfer(const SIPAMICallbackCookiePtr& cookie)
+{
+    Ice::CallbackPtr d = Ice::newCallback(cookie->getSIPAMICallback(), &SIPAMICallback::callback);
+    mSessionRouter->begin_connectBridgedSessions(mOperationId, mSession->getSessionProxy(), mOtherSession->getSessionProxy(), true, d);
+}
+
 SuspendableWorkResult HandleReferOperation::calledBack(const Ice::AsyncResultPtr& asyncResult)
 {
     SessionRouterPrx router = SessionRouterPrx::uncheckedCast(asyncResult->getProxy());
@@ -567,6 +595,43 @@ SuspendableWorkResult HandleReferOperation::calledBack(const Ice::AsyncResultPtr
             router->end_connectBridgedSessions(asyncResult);
         }
     }
+    catch (const Ice::ConnectionLostException &cle)
+    {
+        // Assume a failover is occurring for the routing service. 
+        // This will block the WorkQueue's thread, but it's highly likely
+        // that the failover effects most of the other enqueued operations 
+        // anyway. 
+        if(mRetryPolicy.retry())
+        {
+            lg(Warning) << "HandleReferOperation: Retrying transfer operation.";
+
+            // Retry the operation. 
+            if (mBlindTransfer)
+            {
+                invokeBlindTransfer(SIPAMICallbackCookiePtr::dynamicCast(asyncResult->getCookie()));
+            }
+            else
+            {
+                invokeTransfer(SIPAMICallbackCookiePtr::dynamicCast(asyncResult->getCookie()));
+            }
+        }
+        else
+        {
+            lg(Error) << "ConnectBridgedSessionsCallback sending 400 due to retry failing  " << mRetryPolicy.getMaxRetries() << " retries." ;
+            pjsip_tx_data *tdata = createNotify(mInv->dlg, mReferCSeq, false);
+            if (tdata)
+            {
+                addNotifyBody(tdata, "SIP/2.0 400 Bad Request");
+                pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
+            }
+            //Only blind transfers have the session creation hook to get rid of
+            if (mBlindTransfer)
+            {
+                mHook->shutdown();
+            }
+        }
+        return Complete;
+    }
     catch (const AsteriskSCF::Core::Routing::V1::DestinationNotFoundException&)
     {
         lg(Debug) << "ConnectBridgedSessionsWithDestination sending 404 due to destination not found.";
diff --git a/src/SIPTransfer.h b/src/SIPTransfer.h
index aebc65c..db8927c 100644
--- a/src/SIPTransfer.h
+++ b/src/SIPTransfer.h
@@ -19,6 +19,7 @@
 #include <AsteriskSCF/Discovery/SmartProxy.h>
 #include <AsteriskSCF/Replication/SIPSessionManager/SIPStateReplicationIf.h>
 #include <AsteriskSCF/System/Hook/HookIf.h>
+#include <AsteriskSCF/Helpers/Retry.h>
 
 #include "PJSIPSessionModule.h"
 
@@ -280,6 +281,17 @@ protected:
             const Ice::AsyncResultPtr& asyncResult);
 
 private:
+
+    /** 
+     * Invoke a blind transfer using session routing service. 
+     */
+    void invokeBlindTransfer(const SIPAMICallbackCookiePtr& cookie);
+
+    /** 
+     * Invoke a transfer using session routing service. 
+     */
+    void invokeTransfer(const SIPAMICallbackCookiePtr& cookie);
+
     /**
      * Find matching dialog from the replaces header.
      * This mostly exists just so there isn't a huge
@@ -329,6 +341,10 @@ private:
      */
     SIPSessionPtr mSession;
     /**
+     * The SIPSession that is bridged with the sessions that are being moved in a transfer.
+     */
+    SIPSessionPtr mOtherSession;
+    /**
      * Session router...nothing more to say really
      */
     AsteriskSCF::Discovery::SmartProxy<AsteriskSCF::SessionCommunications::V1::SessionRouterPrx> mSessionRouter;
@@ -359,6 +375,16 @@ private:
      * session fails.
      */
     TransferSessionCreationHookPtr mHook;
+
+    /**
+     * Unique id used for the routing service operation. 
+     */
+    std::string mOperationId;
+
+    /**
+     * Retry helper. 
+     */
+    RetryPolicy mRetryPolicy;
 };
 
 }; //end namespace SIPSessionManager

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


-- 
asterisk-scf/integration/sip.git



More information about the asterisk-scf-commits mailing list