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

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Thu Jul 28 16:46:34 CDT 2011


branch "transfer-improvements" has been updated
       via  6dc4fb170b7ce46665a7b5bda8b51a0d16839ede (commit)
       via  1f8f20c806b604bb903f24bd1b88e4502d337f6d (commit)
       via  0107322adb94249b436546340bd17a760c321540 (commit)
       via  000e0a031874c76c9cc0430a9ffe7809dd7acc60 (commit)
       via  33626a959dc3d70e4e477a522c9ffffb4270a7b4 (commit)
      from  8606dbf96a428332539b91df02e0bd0c342ecf52 (commit)

Summary of changes:
 .../SipSessionManager/SipSessionCookiesIf.ice      |   50 +++++
 src/CMakeLists.txt                                 |    1 +
 src/SipSession.cpp                                 |   91 +++++++--
 src/SipSession.h                                   |    9 +
 src/SipTransfer.cpp                                |  198 ++++++++++++--------
 src/SipTransfer.h                                  |   19 ++-
 6 files changed, 261 insertions(+), 107 deletions(-)
 create mode 100644 slice/AsteriskSCF/SessionCookies/SipSessionManager/SipSessionCookiesIf.ice


- Log -----------------------------------------------------------------
commit 6dc4fb170b7ce46665a7b5bda8b51a0d16839ede
Author: Mark Michelson <mmichelson at digium.com>
Date:   Thu Jul 28 16:46:50 2011 -0500

    Do some cleanup.
    
    Next up is state replication. I am not looking forward to it even a little bit.

diff --git a/src/SipTransfer.cpp b/src/SipTransfer.cpp
index 713b7fd..5a0dec0 100644
--- a/src/SipTransfer.cpp
+++ b/src/SipTransfer.cpp
@@ -193,9 +193,9 @@ public:
         return result;
     }
 
-    void setProxyID(const Ice::Identity& id)
+    void setProxy(const SessionCreationHookPrx& proxy)
     {
-        mProxyID = id;
+        mProxy = proxy;
     }
 
 private:
@@ -217,14 +217,14 @@ private:
 
     void die()
     {
-        mAdapter->remove(mProxyID);
+        mAdapter->remove(mProxy->ice_getIdentity());
     }
 
     Ice::ObjectAdapterPtr mAdapter;
     pjsip_dialog *mDialog;
     pj_int32_t mReferCSeq;
     const std::string mReferredBy;
-    Ice::Identity mProxyID;
+    SessionCreationHookPrx mProxy;
 };
 
 typedef IceUtil::Handle<TransferSessionCreationHook> TransferSessionCreationHookPtr;
@@ -273,47 +273,7 @@ SuspendableWorkResult HandleReferOperation::initial(const SuspendableWorkListene
         }
         else
         {
-            // It is possible for the to and from tag value to be present within the Replaces parameter value, so try to
-            // parse it out
-            std::string replaces_value_tmp = std::string(pj_strbuf(&mReplacesParam->value),
-                    pj_strlen(&mReplacesParam->value));
-            std::vector<std::string> params;
-
-            boost::split(params, replaces_value_tmp, boost::is_any_of(";"));
-
-            //The first value will be the actual replaces value.
-            std::string replaces = params.front();
-
-            std::string to;
-            std::string from;
-            std::string fromTagParamName("from-tag=");
-            std::string toTagParamName("to-tag=");
-            for(std::vector<std::string>::iterator iter = params.begin();
-                    iter != params.end(); ++iter)
-            {
-                if (iter->compare(0, toTagParamName.size(), toTagParamName) == 0)
-                {
-                    to = iter->substr(toTagParamName.size());
-                }
-                if (iter->compare(0, fromTagParamName.size(), fromTagParamName) == 0)
-                {
-                    from = iter->substr(fromTagParamName.size());
-                }
-            }
-
-            if (from.empty() || to.empty())
-            {
-                lg(Debug) << "handleRefer() sending 400 due to From or To missing. ";
-                pjsip_dlg_modify_response(mInv->dlg, mTdata, 400, NULL);
-                pjsip_dlg_send_response(mInv->dlg, mTsx, mTdata);
-                return Complete;
-            }
-
-            pj_str_t to_tag_str = pj_str((char*)to.c_str());
-            pj_str_t from_tag_str = pj_str((char*)from.c_str());
-            pj_str_t replaces_tag_str = pj_str((char*)replaces.c_str());
-
-            other_dlg = pjsip_ua_find_dialog(&replaces_tag_str, &to_tag_str, &from_tag_str, PJ_TRUE);
+            other_dlg = findDialogFromReplaces();
         }
 
         if (!other_dlg)
@@ -369,16 +329,11 @@ SuspendableWorkResult HandleReferOperation::initial(const SuspendableWorkListene
 
             lg(Debug) << "handleRefer() calling router connectBridgedSessions(). ";
 
-            TransferSessionCreationHookPtr hook(new TransferSessionCreationHook(mAdapter, mInv->dlg, mReferCSeq, mReferredBy));
-            SessionCreationHookPrx hookPrx = SessionCreationHookPrx::uncheckedCast(mAdapter->addWithUUID(hook));
-            hook->setProxyID(hookPrx->ice_getIdentity());
-            mHookPrxID = hookPrx->ice_getIdentity();
-
             mSessionRouter->begin_connectBridgedSessions(operationId, mSession->getSessionProxy(), other_session->getSessionProxy(), d);
             pjsip_dlg_dec_lock(other_dlg);
             return Complete;
         }
-        catch (const Ice::CommunicatorDestroyedException &)
+        catch (const Ice::CommunicatorDestroyedException&)
         {
             lg(Debug) << "handleRefer() sending 503 due to communicator destruction";
             pjsip_dlg_modify_response(mInv->dlg, mTdata, 503, NULL);
@@ -392,7 +347,6 @@ SuspendableWorkResult HandleReferOperation::initial(const SuspendableWorkListene
         //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);
-
         // Now that we have the target user we can pass this into routing and go on our marry way
         try
         {
@@ -406,18 +360,15 @@ SuspendableWorkResult HandleReferOperation::initial(const SuspendableWorkListene
             lg(Debug) << "Session to replace is with endpoint " << session->getEndpoint()->getName();
             lg(Debug) << "Destination is " << mTarget;
             mWasWithDestination = true;
-
-            TransferSessionCreationHookPtr hook(new TransferSessionCreationHook(mAdapter, mInv->dlg, mReferCSeq, mReferredBy));
-            SessionCreationHookPrx hookPrx = SessionCreationHookPrx::uncheckedCast(mAdapter->addWithUUID(hook));
-            hook->setProxyID(hookPrx->ice_getIdentity());
-            mHookPrxID = hookPrx->ice_getIdentity();
-
+            
+            createTransferSessionCreationHook();
+            
             //Go ahead and send the 100 Trying sipfrag
             pjsip_tx_data *tdata = createNotify(mInv->dlg, mReferCSeq, true);
             addNotifyBody(tdata, "SIP/2.0 100 Trying");
             pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
 
-            mSessionRouter->begin_connectBridgedSessionsWithDestination(operationId, session->getSessionProxy(), mTarget, hookPrx, d);
+            mSessionRouter->begin_connectBridgedSessionsWithDestination(operationId, session->getSessionProxy(), mTarget, mHookPrx, d);
             return Complete;
         }
         catch (const Ice::CommunicatorDestroyedException &)
@@ -451,7 +402,7 @@ SuspendableWorkResult HandleReferOperation::calledBack(const Ice::AsyncResultPtr
         pjsip_tx_data *tdata = createNotify(mInv->dlg, mReferCSeq, false);
         addNotifyBody(tdata, "SIP/2.0 404 Not Found");
         pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
-        mAdapter->remove(mHookPrxID);
+        mAdapter->remove(mHookPrx->ice_getIdentity());
         return Complete;
     }
     catch (const std::exception& e)
@@ -460,12 +411,60 @@ SuspendableWorkResult HandleReferOperation::calledBack(const Ice::AsyncResultPtr
         pjsip_tx_data *tdata = createNotify(mInv->dlg, mReferCSeq, false);
         addNotifyBody(tdata, "SIP/2.0 400 Bad Request");
         pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
-        mAdapter->remove(mHookPrxID);
+        mAdapter->remove(mHookPrx->ice_getIdentity());
         return Complete;
     }
-    
     return Complete;
 }
 
+void HandleReferOperation::createTransferSessionCreationHook()
+{
+    TransferSessionCreationHookPtr hook(new TransferSessionCreationHook(mAdapter, mInv->dlg, mReferCSeq, mReferredBy));
+    mHookPrx = SessionCreationHookPrx::uncheckedCast(mAdapter->addWithUUID(hook));
+    hook->setProxy(mHookPrx);
+}
+
+pjsip_dialog* HandleReferOperation::findDialogFromReplaces()
+{
+    // It is possible for the to and from tag value to be present within the Replaces parameter value, so try to
+    // parse it out
+    std::string replaces_value_tmp = std::string(pj_strbuf(&mReplacesParam->value),
+            pj_strlen(&mReplacesParam->value));
+    std::vector<std::string> params;
+
+    boost::split(params, replaces_value_tmp, boost::is_any_of(";"));
+
+    //The first value will be the actual replaces value.
+    std::string replaces = params.front();
+
+    std::string to;
+    std::string from;
+    std::string fromTagParamName("from-tag=");
+    std::string toTagParamName("to-tag=");
+    for(std::vector<std::string>::iterator iter = params.begin();
+            iter != params.end(); ++iter)
+    {
+        if (iter->compare(0, toTagParamName.size(), toTagParamName) == 0)
+        {
+            to = iter->substr(toTagParamName.size());
+        }
+        if (iter->compare(0, fromTagParamName.size(), fromTagParamName) == 0)
+        {
+            from = iter->substr(fromTagParamName.size());
+        }
+    }
+
+    if (from.empty() || to.empty())
+    {
+        return NULL;
+    }
+
+    pj_str_t to_tag_str = pj_str((char*)to.c_str());
+    pj_str_t from_tag_str = pj_str((char*)from.c_str());
+    pj_str_t replaces_tag_str = pj_str((char*)replaces.c_str());
+
+    return pjsip_ua_find_dialog(&replaces_tag_str, &to_tag_str, &from_tag_str, PJ_TRUE);
+}
+
 }; //end namespace SipSessionManager
 }; //end namespace AsteriskSCF
diff --git a/src/SipTransfer.h b/src/SipTransfer.h
index bb2ba1d..37ac51f 100644
--- a/src/SipTransfer.h
+++ b/src/SipTransfer.h
@@ -66,6 +66,16 @@ protected:
 
 private:
     /**
+     * Create the transfer session creation hook
+     */
+    void createTransferSessionCreationHook();
+    /**
+     * Find matching dialog from the replaces header.
+     * This mostly exists just so there isn't a huge
+     * block of code in the middle of processing.
+     */
+    pjsip_dialog* findDialogFromReplaces();
+    /**
      * The INVITE session, which contains the dialog on which the
      * REFER was received.
      */
@@ -130,9 +140,11 @@ private:
      */
     bool mWasWithDestination;
     /**
-     * The identity of the session creation hook we create.
+     * The proxy of the session creation hook we create.
+     * We have to hold onto this in case our AMI call to create the outbound
+     * session fails.
      */
-    Ice::Identity mHookPrxID;
+    AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookPrx mHookPrx;
 };
 
 }; //end namespace SipSessionManager

commit 1f8f20c806b604bb903f24bd1b88e4502d337f6d
Author: Mark Michelson <mmichelson at digium.com>
Date:   Thu Jul 28 14:34:15 2011 -0500

    Set up session creation hook on attended transfers.

diff --git a/src/SipTransfer.cpp b/src/SipTransfer.cpp
index 9b9059b..713b7fd 100644
--- a/src/SipTransfer.cpp
+++ b/src/SipTransfer.cpp
@@ -368,6 +368,12 @@ SuspendableWorkResult HandleReferOperation::initial(const SuspendableWorkListene
             Ice::CallbackPtr d = Ice::newCallback(cb, &SipAMICallback::callback);
 
             lg(Debug) << "handleRefer() calling router connectBridgedSessions(). ";
+
+            TransferSessionCreationHookPtr hook(new TransferSessionCreationHook(mAdapter, mInv->dlg, mReferCSeq, mReferredBy));
+            SessionCreationHookPrx hookPrx = SessionCreationHookPrx::uncheckedCast(mAdapter->addWithUUID(hook));
+            hook->setProxyID(hookPrx->ice_getIdentity());
+            mHookPrxID = hookPrx->ice_getIdentity();
+
             mSessionRouter->begin_connectBridgedSessions(operationId, mSession->getSessionProxy(), other_session->getSessionProxy(), d);
             pjsip_dlg_dec_lock(other_dlg);
             return Complete;

commit 0107322adb94249b436546340bd17a760c321540
Author: Mark Michelson <mmichelson at digium.com>
Date:   Thu Jul 28 13:49:53 2011 -0500

    Add some more sipfrag messages.
    
    * 100 Trying immediately
    * 486 on busy user
    * 503 on other failures of the outbound call

diff --git a/src/SipTransfer.cpp b/src/SipTransfer.cpp
index 324c325..9b9059b 100644
--- a/src/SipTransfer.cpp
+++ b/src/SipTransfer.cpp
@@ -113,7 +113,19 @@ public:
         {
             lg(Debug) << "Got the stopped indication. Should send some sort of final response sipfrag NOTIFY";
             pjsip_tx_data *tdata = createNotify(mDialog, mReferCSeq, false);
-            addNotifyBody(tdata, "SIP/2.0 200 OK");
+            //XXX We could stand to add more possible responses here, but for now
+            //just getting things working is my top priority, and we conform to
+            //RFC 3515.
+            switch (stopped->response->isdnCode)
+            {
+                //Busy
+                case 17:
+                    addNotifyBody(tdata, "SIP/2.0 486 Busy Here");
+                //RFC 3515 section 2.4.5 says that we can send a 503 for any reference
+                //that fails.
+                default:
+                    addNotifyBody(tdata, "SIP/2.0 503 Service Unavailable");
+            }
             pjsip_dlg_send_request(mDialog, tdata, -1, NULL);
             die(source);
         }
@@ -388,10 +400,17 @@ SuspendableWorkResult HandleReferOperation::initial(const SuspendableWorkListene
             lg(Debug) << "Session to replace is with endpoint " << session->getEndpoint()->getName();
             lg(Debug) << "Destination is " << mTarget;
             mWasWithDestination = true;
+
             TransferSessionCreationHookPtr hook(new TransferSessionCreationHook(mAdapter, mInv->dlg, mReferCSeq, mReferredBy));
             SessionCreationHookPrx hookPrx = SessionCreationHookPrx::uncheckedCast(mAdapter->addWithUUID(hook));
             hook->setProxyID(hookPrx->ice_getIdentity());
             mHookPrxID = hookPrx->ice_getIdentity();
+
+            //Go ahead and send the 100 Trying sipfrag
+            pjsip_tx_data *tdata = createNotify(mInv->dlg, mReferCSeq, true);
+            addNotifyBody(tdata, "SIP/2.0 100 Trying");
+            pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
+
             mSessionRouter->begin_connectBridgedSessionsWithDestination(operationId, session->getSessionProxy(), mTarget, hookPrx, d);
             return Complete;
         }
@@ -409,9 +428,6 @@ SuspendableWorkResult HandleReferOperation::calledBack(const Ice::AsyncResultPtr
 {
     SessionRouterPrx router = SessionRouterPrx::uncheckedCast(asyncResult->getProxy());
 
-    // We need to send a NOTIFY to indicate how things went on the other leg.
-    // XXX Once we have a subscription module written, we can actually use it.
-
     try
     {
         if (mWasWithDestination)

commit 000e0a031874c76c9cc0430a9ffe7809dd7acc60
Author: Mark Michelson <mmichelson at digium.com>
Date:   Thu Jul 28 13:09:39 2011 -0500

    Add support for a ReferredBy cookie.
    
    Now when a transfer occurs, and a REFER has a Referred-By header,
    we will duplicate this on our outbound INVITE to the transfer target.

diff --git a/slice/AsteriskSCF/SessionCookies/SipSessionManager/SipSessionCookiesIf.ice b/slice/AsteriskSCF/SessionCookies/SipSessionManager/SipSessionCookiesIf.ice
new file mode 100644
index 0000000..e3263e6
--- /dev/null
+++ b/slice/AsteriskSCF/SessionCookies/SipSessionManager/SipSessionCookiesIf.ice
@@ -0,0 +1,50 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+
+#pragma once
+
+#include <AsteriskSCF/SessionCommunications/SessionCommunicationsIf.ice>
+
+module AsteriskSCF
+{
+
+module SessionCookies
+{
+
+module SipSessionManager
+{
+
+["suppress"]
+module V1
+{
+
+/**
+ * When creating an outbound session, if this cookie is present,
+ * then this value should be included in a Referred-By header
+ * on the outbound INVITE.
+ */
+unsliceable class ReferredByCookie extends AsteriskSCF::SessionCommunications::V1::SessionCookie
+{
+    /**
+     * The value of the Referred-By header from a REFER
+     */
+    string value;
+};
+
+}; //end module V1
+}; //end module SipSessionManager
+}; //end module SessionCookies
+}; //end module AsteriskSCF
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 81f2bec..71cfbd9 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -63,6 +63,7 @@ astscf_component_add_files(SipSessionManager SipRegistrarListener.h)
 astscf_component_add_slices(SipSessionManager PROJECT SipIf.ice)
 astscf_component_add_slices(SipSessionManager PROJECT AsteriskSCF/Replication/SipSessionManager/SipStateReplicationIf.ice)
 astscf_component_add_slices(SipSessionManager PROJECT AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice)
+astscf_component_add_slices(SipSessionManager PROJECT AsteriskSCF/SessionCookies/SipSessionManager/SipSessionCookiesIf.ice)
 astscf_component_add_ice_libraries(SipSessionManager IceStorm)
 astscf_component_add_boost_libraries(SipSessionManager core)
 astscf_component_add_slice_collection_libraries(SipSessionManager ASTSCF)
diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index d8d0a76..47fad2e 100755
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -30,6 +30,7 @@
 #include <AsteriskSCF/logger.h>
 #include <AsteriskSCF/System/NAT/NATTraversalIf.h>
 #include <AsteriskSCF/Media/SDP/MediaSDPIf.h>
+#include <AsteriskSCF/SessionCookies/SipSessionManager/SipSessionCookiesIf.h>
 #include "NATOptions.h"
 
 using namespace AsteriskSCF::System::Logging;
@@ -422,7 +423,8 @@ void SipSession::initializePJSIPStructs()
 
 void SipSession::activateIceObjects(const AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookSeq& hooks)
 {
-    AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookDataPtr initial(new AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookData(mImplPriv->mSessionProxy, mImplPriv->mListeners));
+    AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookDataPtr initial(
+            new AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookData(mImplPriv->mSessionProxy, mImplPriv->mListeners, getCookies()));
 
     AsteriskSCF::SessionCommunications::ExtensionPoints::V1::SessionCreationHookDataPtr in = initial;
 
@@ -448,6 +450,11 @@ void SipSession::activateIceObjects(const AsteriskSCF::SessionCommunications::Ex
             mImplPriv->mPublicSessionProxy = out->session;
             mImplPriv->mListeners.clear();
             mImplPriv->mListeners = out->listeners;
+            // Note this is the setCookies method
+            // typically called from a queued operation.
+            // It's safe to do here since the session is
+            // in the process of being created.
+            setCookies(out->cookies);
             in = out;
         }
     }
@@ -953,12 +960,49 @@ public:
             return Complete;
         }
 
+        addReferredBy(packet);
+
         // Boom! Houston, we have transmission.
         pjsip_inv_send_msg(mImplPriv->mInviteSession, packet);
         return Complete;
     }
 
 private:
+    /**
+     * If this session is being started as the result of
+     * a transfer, there may be a Referred-By header to
+     * include.
+     */
+    void addReferredBy(pjsip_tx_data *packet)
+    {
+        AsteriskSCF::SessionCommunications::V1::SessionCookieDict::const_iterator iter =
+            mImplPriv->mSessionCookies.find(AsteriskSCF::SessionCookies::SipSessionManager::V1::ReferredByCookie::ice_staticId());
+
+        if (iter == mImplPriv->mSessionCookies.end())
+        {
+            lg(Debug) << "No ReferredBy cookie present";
+            return;
+        }
+
+        AsteriskSCF::SessionCookies::SipSessionManager::V1::ReferredByCookiePtr referredBy = 
+            AsteriskSCF::SessionCookies::SipSessionManager::V1::ReferredByCookiePtr::dynamicCast(iter->second);
+
+        if (referredBy->value.empty())
+        {
+            lg(Debug) << "Referred-By is empty.";
+            return;
+        }
+
+        pj_str_t referredByHdrStr;
+        pj_cstr(&referredByHdrStr, "Referred-By");
+        pj_str_t referredByValStr;
+        pj_cstr(&referredByValStr, referredBy->value.c_str());
+
+        pjsip_generic_string_hdr *hdr =
+            pjsip_generic_string_hdr_create(packet->pool, &referredByHdrStr, &referredByValStr);
+
+        pjsip_msg_add_hdr(packet->msg, (pjsip_hdr*) hdr);
+    }
     SipSessionPtr mSession;
     boost::shared_ptr<SipSessionPriv> mImplPriv;
 };
@@ -1023,32 +1067,18 @@ class SetCookiesOperation : public SuspendableWork
 {
 public:
     SetCookiesOperation(const AsteriskSCF::SessionCommunications::V1::SessionCookies& cookies,
-                        const boost::shared_ptr<SipSessionPriv>& sessionPriv)
-        : mCookies(cookies), mImplPriv(sessionPriv) { }
+                        const SipSessionPtr& session)
+        : mCookies(cookies), mSession(session) { }
 
     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
     {
-        for (AsteriskSCF::SessionCommunications::V1::SessionCookies::const_iterator i = mCookies.begin();
-             i != mCookies.end();
-             ++i)
-        {
-            mImplPriv->mSessionCookies.erase((*i)->ice_id());
-            mImplPriv->mSessionCookies.insert(make_pair((*i)->ice_id(), (*i)));
-        }
-
-        if (mImplPriv->mInviteSession)
-        {
-            PJSipSessionModInfo *session_mod_info = static_cast<PJSipSessionModInfo*>(mImplPriv->mInviteSession->mod_data[mImplPriv->mManager->getSessionModule()->getModule().id]);
-            session_mod_info->updateSessionState(mImplPriv->mInviteSession);
-            mImplPriv->mManager->getSessionModule()->replicateState(NULL, NULL, session_mod_info);
-        }
-
+        mSession->setCookies(mCookies);
         return Complete;
     }
 
 private:
     AsteriskSCF::SessionCommunications::V1::SessionCookies mCookies;
-    boost::shared_ptr<SipSessionPriv> mImplPriv;
+    SipSessionPtr mSession;
 };
 
 /**
@@ -1058,7 +1088,28 @@ private:
 void SipSession::setCookies(const AsteriskSCF::SessionCommunications::V1::SessionCookies& cookies, const Ice::Current&)
 {
     lg(Debug) << "queuing a setCookies operation";
-    enqueueSessionWork(new SetCookiesOperation(cookies, mImplPriv));
+    enqueueSessionWork(new SetCookiesOperation(cookies, this));
+}
+
+/**
+ * Typically called from queued operations
+ */
+void SipSession::setCookies(const AsteriskSCF::SessionCommunications::V1::SessionCookies& cookies)
+{
+   for (AsteriskSCF::SessionCommunications::V1::SessionCookies::const_iterator i = cookies.begin();
+        i != cookies.end();
+        ++i)
+   {
+       mImplPriv->mSessionCookies.erase((*i)->ice_id());
+       mImplPriv->mSessionCookies.insert(make_pair((*i)->ice_id(), (*i)));
+   }
+
+   if (mImplPriv->mInviteSession)
+   {
+       PJSipSessionModInfo *session_mod_info = static_cast<PJSipSessionModInfo*>(mImplPriv->mInviteSession->mod_data[mImplPriv->mManager->getSessionModule()->getModule().id]);
+       session_mod_info->updateSessionState(mImplPriv->mInviteSession);
+       mImplPriv->mManager->getSessionModule()->replicateState(NULL, NULL, session_mod_info);
+   }
 }
 
 /**
diff --git a/src/SipSession.h b/src/SipSession.h
index ad50231..2d6c3e9 100644
--- a/src/SipSession.h
+++ b/src/SipSession.h
@@ -178,6 +178,15 @@ public:
     void stop(const AsteriskSCF::SessionCommunications::V1::ResponseCodePtr&, const Ice::Current&);
     void unhold(const Ice::Current&);
     void setCookies(const AsteriskSCF::SessionCommunications::V1::SessionCookies&, const Ice::Current&);
+    /**
+     * Typically called from queued operations to set cookies.
+     * Also used during session creation when modifications hooks have changed
+     * the cookies
+     */
+    void setCookies(const AsteriskSCF::SessionCommunications::V1::SessionCookies&);
+    /**
+     * Used during replication
+     */
     void setCookies(const AsteriskSCF::SessionCommunications::V1::SessionCookieDict&);
     void removeCookies(const AsteriskSCF::SessionCommunications::V1::SessionCookies&, const Ice::Current&);
     AsteriskSCF::SessionCommunications::V1::SessionCookies getCookies(const AsteriskSCF::SessionCommunications::V1::SessionCookies&, const Ice::Current&);
diff --git a/src/SipTransfer.cpp b/src/SipTransfer.cpp
index 002f338..324c325 100644
--- a/src/SipTransfer.cpp
+++ b/src/SipTransfer.cpp
@@ -21,6 +21,7 @@
 
 #include <AsteriskSCF/logger.h>
 #include <AsteriskSCF/SessionCommunications/SessionCommunicationsExtensionPointsIf.h>
+#include <AsteriskSCF/SessionCookies/SipSessionManager/SipSessionCookiesIf.h>
 
 using namespace AsteriskSCF::System::Logging;
 
@@ -28,7 +29,7 @@ namespace
 {
 Logger lg = getLoggerFactory().getLogger("AsteriskSCF.SipSessionManager");
 
-pjsip_tx_data* createNotify(pjsip_dialog *dlg, pj_int32_t cseq)
+pjsip_tx_data* createNotify(pjsip_dialog *dlg, pj_int32_t cseq, bool active)
 {
     pjsip_tx_data *tdata;
     pjsip_dlg_create_request(dlg, pjsip_get_notify_method(), -1, &tdata);
@@ -41,8 +42,15 @@ pjsip_tx_data* createNotify(pjsip_dialog *dlg, pj_int32_t cseq)
     pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*) event);
 
     pjsip_sub_state_hdr *subState = pjsip_sub_state_hdr_create(tdata->pool);
-    pj_strdup2(tdata->pool, &subState->sub_state, "terminated");
-    pj_strdup2(tdata->pool, &subState->reason_param, "noresource");
+    if (active)
+    {
+        pj_strdup2(tdata->pool, &subState->sub_state, "active");
+    }
+    else
+    {
+        pj_strdup2(tdata->pool, &subState->sub_state, "terminated");
+        pj_strdup2(tdata->pool, &subState->reason_param, "noresource");
+    }
     pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*) subState);
 
     return tdata;
@@ -73,6 +81,7 @@ using namespace AsteriskSCF::SessionCommunications::V1;
 using namespace AsteriskSCF::SessionCommunications::ExtensionPoints::V1;
 using namespace AsteriskSCF::System::WorkQueue::V1;
 using namespace AsteriskSCF::System::Hook::V1;
+using namespace AsteriskSCF::SessionCookies::SipSessionManager::V1;
 
 class TransferListener : public SessionListener
 {
@@ -85,7 +94,7 @@ public:
     void indicated(
             const SessionPrx& source,
             const IndicationPtr& event,
-            const SessionCookies&,
+            const AsteriskSCF::SessionCommunications::V1::SessionCookies&,
             const Ice::Current&)
     {
         ConnectedIndicationPtr connected;
@@ -95,7 +104,7 @@ public:
         if ((connected = ConnectedIndicationPtr::dynamicCast(event)))
         {
             lg(Debug) << "Got the connected indication. Should send a 200 sipfrag NOTIFY";
-            pjsip_tx_data *tdata = createNotify(mDialog, mReferCSeq);
+            pjsip_tx_data *tdata = createNotify(mDialog, mReferCSeq, false);
             addNotifyBody(tdata, "SIP/2.0 200 OK");
             pjsip_dlg_send_request(mDialog, tdata, -1, NULL);
             die(source);
@@ -103,7 +112,7 @@ public:
         else if ((stopped = StoppedIndicationPtr::dynamicCast(event)))
         {
             lg(Debug) << "Got the stopped indication. Should send some sort of final response sipfrag NOTIFY";
-            pjsip_tx_data *tdata = createNotify(mDialog, mReferCSeq);
+            pjsip_tx_data *tdata = createNotify(mDialog, mReferCSeq, false);
             addNotifyBody(tdata, "SIP/2.0 200 OK");
             pjsip_dlg_send_request(mDialog, tdata, -1, NULL);
             die(source);
@@ -111,14 +120,14 @@ public:
         else if ((ringing = RingingIndicationPtr::dynamicCast(event)))
         {
             lg(Debug) << "Got a ringing indication. Should send a 180 sipfrag NOTIFY";
-            pjsip_tx_data *tdata = createNotify(mDialog, mReferCSeq);
+            pjsip_tx_data *tdata = createNotify(mDialog, mReferCSeq, true);
             addNotifyBody(tdata, "SIP/2.0 180 Ringing");
             pjsip_dlg_send_request(mDialog, tdata, -1, NULL);
         }
         else if ((progressing = ProgressingIndicationPtr::dynamicCast(event)))
         {
             lg(Debug) << "Got a progressing indication. Should send a 183 sipfrag NOTIFY";
-            pjsip_tx_data *tdata = createNotify(mDialog, mReferCSeq);
+            pjsip_tx_data *tdata = createNotify(mDialog, mReferCSeq, true);
             addNotifyBody(tdata, "SIP/2.0 183 Session Progress");
             pjsip_dlg_send_request(mDialog, tdata, -1, NULL);
         }
@@ -151,8 +160,9 @@ public:
     TransferSessionCreationHook(
             const Ice::ObjectAdapterPtr& adapter,
             pjsip_dialog *dlg,
-            pj_int32_t referCSeq)
-        : mAdapter(adapter), mDialog(dlg), mReferCSeq(referCSeq)
+            pj_int32_t referCSeq,
+            const std::string& referredBy)
+        : mAdapter(adapter), mDialog(dlg), mReferCSeq(referCSeq), mReferredBy(referredBy)
     {
     }
 
@@ -186,7 +196,10 @@ private:
         transferListener->setProxy(transferListenerPrx);
         SessionListenerSeq listeners = original->listeners;
         listeners.push_back(transferListenerPrx);
+        AsteriskSCF::SessionCommunications::V1::SessionCookies cookies = original->cookies;
+        cookies.push_back(new ReferredByCookie(mReferredBy));
         replacement->session = original->session;
+        replacement->cookies = cookies;
         replacement->listeners = listeners;
     }
 
@@ -198,6 +211,7 @@ private:
     Ice::ObjectAdapterPtr mAdapter;
     pjsip_dialog *mDialog;
     pj_int32_t mReferCSeq;
+    const std::string mReferredBy;
     Ice::Identity mProxyID;
 };
 
@@ -374,7 +388,7 @@ SuspendableWorkResult HandleReferOperation::initial(const SuspendableWorkListene
             lg(Debug) << "Session to replace is with endpoint " << session->getEndpoint()->getName();
             lg(Debug) << "Destination is " << mTarget;
             mWasWithDestination = true;
-            TransferSessionCreationHookPtr hook(new TransferSessionCreationHook(mAdapter, mInv->dlg, mReferCSeq));
+            TransferSessionCreationHookPtr hook(new TransferSessionCreationHook(mAdapter, mInv->dlg, mReferCSeq, mReferredBy));
             SessionCreationHookPrx hookPrx = SessionCreationHookPrx::uncheckedCast(mAdapter->addWithUUID(hook));
             hook->setProxyID(hookPrx->ice_getIdentity());
             mHookPrxID = hookPrx->ice_getIdentity();
@@ -398,8 +412,6 @@ SuspendableWorkResult HandleReferOperation::calledBack(const Ice::AsyncResultPtr
     // We need to send a NOTIFY to indicate how things went on the other leg.
     // XXX Once we have a subscription module written, we can actually use it.
 
-    pjsip_tx_data *tdata = createNotify(mInv->dlg, mReferCSeq);
-    
     try
     {
         if (mWasWithDestination)
@@ -414,7 +426,7 @@ SuspendableWorkResult HandleReferOperation::calledBack(const Ice::AsyncResultPtr
     catch (const AsteriskSCF::Core::Routing::V1::DestinationNotFoundException&)
     {
         lg(Debug) << "ConnectBridgedSessionsWithDestination sending 404 due to destination not found.";
-
+        pjsip_tx_data *tdata = createNotify(mInv->dlg, mReferCSeq, false);
         addNotifyBody(tdata, "SIP/2.0 404 Not Found");
         pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
         mAdapter->remove(mHookPrxID);
@@ -423,7 +435,7 @@ SuspendableWorkResult HandleReferOperation::calledBack(const Ice::AsyncResultPtr
     catch (const std::exception& e)
     {
         lg(Debug) << "ConnectBridgedSessionsCallback sending 400 due to exception:  " << e.what();
-
+        pjsip_tx_data *tdata = createNotify(mInv->dlg, mReferCSeq, false);
         addNotifyBody(tdata, "SIP/2.0 400 Bad Request");
         pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
         mAdapter->remove(mHookPrxID);
diff --git a/src/SipTransfer.h b/src/SipTransfer.h
index f607429..bb2ba1d 100644
--- a/src/SipTransfer.h
+++ b/src/SipTransfer.h
@@ -96,9 +96,6 @@ private:
     pjsip_param *mFromTagParam;
     /**
      * The content from the Referred-By header, if one existed.
-     * XXX We currently have this handy, but we don't actually do
-     * anything with it. This is because we don't have a way to place
-     * this information in the outgoing INVITE.
      */
     const std::string mReferredBy;
     /**

commit 33626a959dc3d70e4e477a522c9ffffb4270a7b4
Author: Mark Michelson <mmichelson at digium.com>
Date:   Thu Jul 28 10:33:33 2011 -0500

    Be sure to remove the session listener once we're done with it.

diff --git a/src/SipTransfer.cpp b/src/SipTransfer.cpp
index 1a6e63b..002f338 100644
--- a/src/SipTransfer.cpp
+++ b/src/SipTransfer.cpp
@@ -83,7 +83,7 @@ public:
     }
 
     void indicated(
-            const SessionPrx&,
+            const SessionPrx& source,
             const IndicationPtr& event,
             const SessionCookies&,
             const Ice::Current&)
@@ -98,7 +98,7 @@ public:
             pjsip_tx_data *tdata = createNotify(mDialog, mReferCSeq);
             addNotifyBody(tdata, "SIP/2.0 200 OK");
             pjsip_dlg_send_request(mDialog, tdata, -1, NULL);
-            die();
+            die(source);
         }
         else if ((stopped = StoppedIndicationPtr::dynamicCast(event)))
         {
@@ -106,7 +106,7 @@ public:
             pjsip_tx_data *tdata = createNotify(mDialog, mReferCSeq);
             addNotifyBody(tdata, "SIP/2.0 200 OK");
             pjsip_dlg_send_request(mDialog, tdata, -1, NULL);
-            die();
+            die(source);
         }
         else if ((ringing = RingingIndicationPtr::dynamicCast(event)))
         {
@@ -124,21 +124,22 @@ public:
         }
     }
 
-    void setProxyID(const Ice::Identity& id)
+    void setProxy(const SessionListenerPrx& listener)
     {
-        mProxyID = id;
+        mListenerProxy = listener;
     }
 private:
 
-    void die()
+    void die(const SessionPrx& session)
     {
-        mAdapter->remove(mProxyID);
+        session->removeListener(mListenerProxy);
+        mAdapter->remove(mListenerProxy->ice_getIdentity());
     }
 
     Ice::ObjectAdapterPtr mAdapter;
     pjsip_dialog *mDialog;
     pj_int32_t mReferCSeq;
-    Ice::Identity mProxyID;
+    SessionListenerPrx mListenerProxy;
 };
 
 typedef IceUtil::Handle<TransferListener> TransferListenerPtr;
@@ -182,7 +183,7 @@ private:
     {
         TransferListenerPtr transferListener = new TransferListener(mAdapter, mDialog, mReferCSeq);
         SessionListenerPrx transferListenerPrx = SessionListenerPrx::uncheckedCast(mAdapter->addWithUUID(transferListener));
-        transferListener->setProxyID(transferListenerPrx->ice_getIdentity());
+        transferListener->setProxy(transferListenerPrx);
         SessionListenerSeq listeners = original->listeners;
         listeners.push_back(transferListenerPrx);
         replacement->session = original->session;

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


-- 
asterisk-scf/integration/sip.git



More information about the asterisk-scf-commits mailing list