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

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Mon May 16 17:07:47 CDT 2011


branch "threading" has been updated
       via  623654b3e60749219d9fa790649f6833200c708f (commit)
       via  d64aea41b53bc585a88fa155bffe6c02562f29af (commit)
       via  72aedeaee32c837c3978f8e91d35af258dd6c880 (commit)
       via  349e921f0cc58898d43db5330643fc3789b0e7bf (commit)
       via  e9d1aa434ba33120497c9dee97ef386f955753b3 (commit)
      from  080f90db10d408e73b4dc9e8eeea8f32c5c0fcb1 (commit)

Summary of changes:
 src/PJSipModule.h          |    2 +-
 src/PJSipSessionModule.cpp |  386 ++++++++++++++++++++++++++++++-------------
 src/PJSipSessionModule.h   |   28 +++-
 3 files changed, 297 insertions(+), 119 deletions(-)


- Log -----------------------------------------------------------------
commit 623654b3e60749219d9fa790649f6833200c708f
Author: Mark Michelson <mmichelson at digium.com>
Date:   Mon May 16 17:07:48 2011 -0500

    Rearrange things so that code compiles.

diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 20060c5..e8acc3e 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -1186,6 +1186,60 @@ void PJSipSessionModule::handleInviteResponse(pjsip_inv_session* inv,
     session->enqueueSessionWork(new HandleInviteResponseOperation(respCode, inv->state, session));
 }
 
+class TransactionStateOperation : public SipQueueableOperation
+{
+public:
+    TransactionStateOperation(
+            const PJSipSessionModulePtr& module,
+            pjsip_transaction *tsx,
+            pjsip_inv_session *inv,
+            const int eventType,
+            const int tsxState)
+        : mSessionModule(module), mTsx(tsx), mInv(inv), mEventType(eventType), mTsxState(tsxState) { }
+
+    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+    {
+        PJSipTransactionModInfo *tsx_mod_info = static_cast<PJSipTransactionModInfo *> (mTsx->mod_data[mSessionModule->getModule().id]);
+        if (mTsxState != PJSIP_TSX_STATE_DESTROYED)
+        {
+            tsx_mod_info->updateTransactionState(mTsx);
+        }
+        else
+        {
+            tsx_mod_info->mNeedsRemoval = true;
+        }
+        if (mEventType == PJSIP_EVENT_TSX_STATE)
+        {
+            pjsip_dialog *dlg = pjsip_tsx_get_dlg(mTsx);
+            PJSipDialogModInfo *dlg_mod_info = NULL;
+            if (dlg)
+            {
+                dlg_mod_info = static_cast<PJSipDialogModInfo*>(dlg->mod_data[mSessionModule->getModule().id]);
+                dlg_mod_info->updateDialogState(dlg);
+            }
+            PJSipSessionModInfo *session_mod_info = static_cast<PJSipSessionModInfo*>(mInv->mod_data[mSessionModule->getModule().id]);
+            if (session_mod_info)
+            {
+                session_mod_info->updateSessionState(mInv);
+            }
+            lg(Debug) << "Replicating state on transaction state change to " << mTsxState;
+            mSessionModule->replicateState(dlg_mod_info, tsx_mod_info, session_mod_info);
+        }
+        else if (mEventType == PJSIP_EVENT_TIMER)
+        {
+            lg(Debug) << "Replicating state on transaction state change to " << mTsxState;
+            mSessionModule->replicateState(NULL, tsx_mod_info, NULL);
+        }
+        return Complete;
+    }
+
+    PJSipSessionModulePtr mSessionModule;
+    pjsip_transaction *mTsx;
+    pjsip_inv_session *mInv;
+    const int mEventType;
+    const int mTsxState;
+};
+
 class InviteStateOperation : public SipQueueableOperation
 {
 public:
@@ -1327,60 +1381,6 @@ void PJSipSessionModule::invOnNewSession(pjsip_inv_session*, pjsip_event*)
     //stub
 }
 
-class TransactionStateOperation : public SipQueueableOperation
-{
-public:
-    TransactionStateOperation(
-            const PJSipSessionModulePtr& module,
-            pjsip_transaction *tsx,
-            pjsip_inv_session *inv,
-            const int eventType,
-            const int tsxState)
-        : mSessionModule(module), mTsx(tsx), mInv(inv), mEventType(eventType), mTsxState(tsxState) { }
-
-    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
-    {
-        PJSipTransactionModInfo *tsx_mod_info = static_cast<PJSipTransactionModInfo *> (mTsx->mod_data[mSessionModule->getModule().id]);
-        if (mTsxState != PJSIP_TSX_STATE_DESTROYED)
-        {
-            tsx_mod_info->updateTransactionState(mTsx);
-        }
-        else
-        {
-            tsx_mod_info->mNeedsRemoval = true;
-        }
-        if (mEventType == PJSIP_EVENT_TSX_STATE)
-        {
-            pjsip_dialog *dlg = pjsip_tsx_get_dlg(mTsx);
-            PJSipDialogModInfo *dlg_mod_info = NULL;
-            if (dlg)
-            {
-                dlg_mod_info = static_cast<PJSipDialogModInfo*>(dlg->mod_data[mSessionModule->getModule().id]);
-                dlg_mod_info->updateDialogState(dlg);
-            }
-            PJSipSessionModInfo *session_mod_info = static_cast<PJSipSessionModInfo*>(mInv->mod_data[mSessionModule->getModule().id]);
-            if (session_mod_info)
-            {
-                session_mod_info->updateSessionState(mInv);
-            }
-            lg(Debug) << "Replicating state on transaction state change to " << mTsxState;
-            mSessionModule->replicateState(dlg_mod_info, tsx_mod_info, session_mod_info);
-        }
-        else if (mEventType == PJSIP_EVENT_TIMER)
-        {
-            lg(Debug) << "Replicating state on transaction state change to " << mTsxState;
-            mSessionModule->replicateState(NULL, tsx_mod_info, NULL);
-        }
-        return Complete;
-    }
-
-    PJSipSessionModulePtr mSessionModule;
-    pjsip_transaction *mTsx;
-    pjsip_inv_session *mInv;
-    const int mEventType;
-    const int mTsxState;
-};
-
 void PJSipSessionModule::invOnTsxStateChanged(pjsip_inv_session *inv, pjsip_transaction *tsx, pjsip_event *e)
 {
     if (tsx->role == PJSIP_ROLE_UAS && tsx->state == PJSIP_TSX_STATE_TRYING &&

commit d64aea41b53bc585a88fa155bffe6c02562f29af
Author: Mark Michelson <mmichelson at digium.com>
Date:   Mon May 16 17:06:29 2011 -0500

    Add SessionCreationOperation.
    
    This one's a bit on the oddball side.

diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 9f2f459..20060c5 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -356,6 +356,100 @@ pj_status_t PJSipSessionModule::unload()
     return PJ_SUCCESS;
 }
 
+class SessionCreationOperation : public SipQueueableOperation
+{
+public:
+    SessionCreationOperation(
+            const PJSipSessionModulePtr& module,
+            const SipEndpointPtr& caller,
+            const AsteriskSCF::SmartProxy::SmartProxy<SessionRouterPrx>& router,
+            pjsip_inv_session *inv,
+            pjsip_tx_data *tdata,
+            pjsip_dialog *replacedDialog,
+            const std::string destination)
+        : mSessionModule(module), mCaller(caller), mSessionRouter(router), mInv(inv), mTdata(tdata), mReplacedDialog(replacedDialog), mDestination(destination) { }
+
+    void execute()
+    {
+        try
+        {
+            mSession = mCaller->createSession(mDestination);
+        }
+        catch (const Ice::Exception& ex)
+        {
+            lg(Error) << "Exception caught while trying to create SIP session\n" << ex.what();
+            pjsip_inv_end_session(mInv, 500, NULL, &mTdata);
+            pjsip_inv_send_msg(mInv, mTdata);
+            return;
+        }
+        mSession->setInviteSession(mInv);
+        mSession->setDialog(mInv->dlg);
+        PJSipSessionModInfo *session_mod_info = new PJSipSessionModInfo(mInv, mSession);
+        PJSipDialogModInfo *dlg_mod_info = new PJSipDialogModInfo(mInv->dlg);
+        PJSipTransactionModInfo *tsx_mod_info = new PJSipTransactionModInfo(mInv->invite_tsx);
+        dlg_mod_info->mDialogState->mSessionId = session_mod_info->mSessionState->mSessionId;
+        tsx_mod_info->mTransactionState->mSessionId = session_mod_info->mSessionState->mSessionId;
+    
+        mInv->mod_data[mSessionModule->getModule().id] = (void *)session_mod_info;
+        mInv->dlg->mod_data[mSessionModule->getModule().id] = (void *)dlg_mod_info;
+    
+        lg(Debug) << "Replicating state on reception of new SIP INVITE.";
+        mSessionModule->replicateState(dlg_mod_info, tsx_mod_info, session_mod_info);
+        try
+        {
+            if (mReplacedDialog)
+            {
+                // For attended transfers we need to contact the routing service which should then (hopefully) replace the
+                // other session
+            }
+            else
+            {
+                // If this is not an attended transfer we can just route the session as normally
+                std::string operationId = ::IceUtil::generateUUID();
+                SuspendableWorkListenerPtr listener = 0;
+                SipAMICallbackPtr cb(new SipAMICallback(listener, mSession, this, false, true));
+                Ice::CallbackPtr d = Ice::newCallback(cb, &SipAMICallback::callback);
+                mSessionRouter->begin_routeSession(operationId, mSession->getSessionProxy(), mDestination, d);
+            }
+        }
+        catch (const Ice::CommunicatorDestroyedException &)
+        {
+            // Everything else doesn't really map so they just become internal server errors
+            pjsip_inv_end_session(mInv, 500, NULL, &mTdata);
+            pjsip_inv_send_msg(mInv, mTdata);
+        }
+    }
+
+    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+    {
+        SessionRouterPrx router = SessionRouterPrx::uncheckedCast(mAsyncResult->getProxy());
+        try
+        {
+            router->end_routeSession(mAsyncResult);
+        }
+        catch (const DestinationNotFoundException &)
+        {
+            pjsip_inv_end_session(mInv, 404, NULL, &mTdata);
+            pjsip_inv_send_msg(mInv, mTdata);
+        }
+        catch (...)
+        {
+            pjsip_inv_end_session(mInv, 500, NULL, &mTdata);
+            pjsip_inv_send_msg(mInv, mTdata);
+        }
+        return Complete;
+    }
+
+    PJSipSessionModulePtr mSessionModule;
+    SipEndpointPtr mCaller;
+    AsteriskSCF::SmartProxy::SmartProxy<SessionRouterPrx> mSessionRouter;
+    pjsip_inv_session *mInv;
+    pjsip_tx_data *mTdata;
+    pjsip_dialog *mReplacedDialog;
+    const std::string mDestination;
+    SipSessionPtr mSession;
+};
+
 void PJSipSessionModule::handleNewInvite(pjsip_rx_data *rdata)
 {
     //What do we do here?
@@ -505,6 +599,11 @@ void PJSipSessionModule::handleNewInvite(pjsip_rx_data *rdata)
     //return to us and we can complete the session creation operation and then call out to the
     //routing service and again return "Suspended." Then once *THAT* returns, we can finally
     //return "Complete".
+
+    //We can't do our typical thing of queuing work onto a session here since the session hasn't
+    //yet been created. Instead, we just queue an operation onto the thread pool's queue directly.
+
+    mPoolQueue->enqueueWork(new SessionCreationOperation(this, caller, mSessionRouter, inv_session, tdata, replaced_dlg, destination));
     
     SipSessionPtr session;
     try
diff --git a/src/PJSipSessionModule.h b/src/PJSipSessionModule.h
index 9d9f4a9..b2be3be 100644
--- a/src/PJSipSessionModule.h
+++ b/src/PJSipSessionModule.h
@@ -127,11 +127,35 @@ private:
 
 typedef IceUtil::Handle<PJSipSessionModule> PJSipSessionModulePtr;
 
-class SipQueueableOperation : virtual public AsteriskSCF::System::WorkQueue::V1::SuspendableWork
+/**
+ * Operation that may be queued.
+ *
+ * This inherits from both Work and Suspendable work so that it may
+ * be enqueued in either a WorkQueue or SuspendableWorkQueue.
+ */
+class SipQueueableOperation : virtual public AsteriskSCF::System::WorkQueue::V1::Work, virtual public AsteriskSCF::System::WorkQueue::V1::SuspendableWork
 {
 public:
     virtual ~SipQueueableOperation();
+    /**
+     * Queueable operations may call out to AMI methods. AMI callbacks happen
+     * in Ice client threads. We want to process the result of the AMI call in one
+     * of our thread pool's threads, though. The AMI callback can set the operation's
+     * AsyncResult so that the operation will be able to actually do something with
+     * the AMI call's result.
+     */
     void setAsyncResult(const Ice::AsyncResultPtr& r) {mAsyncResult = r;}
+    /**
+     * Override of Work::execute()
+     */
+    virtual void execute() { }
+    /**
+     * Override of SuspendableWorkExecute()
+     */
+    virtual AsteriskSCF::System::WorkQueue::V1::SuspendableWorkResult execute(const AsteriskSCF::System::WorkQueue::V1::SuspendableWorkListenerPtr&)
+    {
+        return AsteriskSCF::System::WorkQueue::V1::Complete;
+    }
 protected:
     Ice::AsyncResultPtr mAsyncResult;
     SipQueueableOperation();

commit 72aedeaee32c837c3978f8e91d35af258dd6c880
Author: Mark Michelson <mmichelson at digium.com>
Date:   Mon May 16 14:18:29 2011 -0500

    Add comment explaining that invOnRxOffer purposefully does no queuing.

diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 6156413..9f2f459 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -1307,6 +1307,9 @@ void PJSipSessionModule::invOnTsxStateChanged(pjsip_inv_session *inv, pjsip_tran
     session->enqueueSessionWork(new TransactionStateOperation(this, tsx, inv, e->type, tsx->state));
 }
 
+/**
+ * This is the only of the PJSIP callbacks that involves no queueing. 
+ */
 void PJSipSessionModule::invOnRxOffer(pjsip_inv_session* inv, const pjmedia_sdp_session*)
 {
     PJSipSessionModInfo *session_mod_info = (PJSipSessionModInfo*)inv->mod_data[mModule.id];

commit 349e921f0cc58898d43db5330643fc3789b0e7bf
Author: Mark Michelson <mmichelson at digium.com>
Date:   Mon May 16 14:06:20 2011 -0500

    Added transaction state operation.
    
    There's a compilation error still in the invite state operation. I'll
    fix it next.

diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index bf16b21..6156413 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -1157,7 +1157,6 @@ public:
         {
             //We received an ACK for our 2XX response.
             //See comment in invOnTransactionStateChanged() for explanation of this.
-    
             PJSipSessionModInfo *session_mod_info = static_cast<PJSipSessionModInfo*>(mInv->mod_data[mSessionModule->getModule().id]);
             if (session_mod_info)
             {
@@ -1170,9 +1169,15 @@ public:
             if (mInv->invite_tsx && mEventBranch != invBranch)
             {
                 //Mismatched branch!
-                //XXX This needs to be changed to queue a transaction state change operation. That
-                //way, we won't require the entire event. Live with this not compiling at the moment.
-                mSessionModule->invOnTsxStateChanged(mInv, mInv->invite_tsx, event);
+                //XXX There's a check for if session_mod_info is NULL above. I don't
+                //know why session_mod_info would be NULL here since we should have created
+                //the session_mod_info when the INVITE was received. Still, I'm being safe
+                //here.
+                if (session_mod_info)
+                {
+                    SipSessionPtr session = session_mod_info->getSessionPtr();
+                    session->enqueueSessionWork(new TransactionStateOperation(mSessionModule, mInv->invite_tsx, mInv, mEventType, mInv->invite_tsx->state));
+                }
             }
         }
         if (mEventType == PJSIP_EVENT_TSX_STATE && mInvState == PJSIP_INV_STATE_CALLING && mInv->role == PJSIP_ROLE_UAC)
@@ -1223,6 +1228,60 @@ void PJSipSessionModule::invOnNewSession(pjsip_inv_session*, pjsip_event*)
     //stub
 }
 
+class TransactionStateOperation : public SipQueueableOperation
+{
+public:
+    TransactionStateOperation(
+            const PJSipSessionModulePtr& module,
+            pjsip_transaction *tsx,
+            pjsip_inv_session *inv,
+            const int eventType,
+            const int tsxState)
+        : mSessionModule(module), mTsx(tsx), mInv(inv), mEventType(eventType), mTsxState(tsxState) { }
+
+    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+    {
+        PJSipTransactionModInfo *tsx_mod_info = static_cast<PJSipTransactionModInfo *> (mTsx->mod_data[mSessionModule->getModule().id]);
+        if (mTsxState != PJSIP_TSX_STATE_DESTROYED)
+        {
+            tsx_mod_info->updateTransactionState(mTsx);
+        }
+        else
+        {
+            tsx_mod_info->mNeedsRemoval = true;
+        }
+        if (mEventType == PJSIP_EVENT_TSX_STATE)
+        {
+            pjsip_dialog *dlg = pjsip_tsx_get_dlg(mTsx);
+            PJSipDialogModInfo *dlg_mod_info = NULL;
+            if (dlg)
+            {
+                dlg_mod_info = static_cast<PJSipDialogModInfo*>(dlg->mod_data[mSessionModule->getModule().id]);
+                dlg_mod_info->updateDialogState(dlg);
+            }
+            PJSipSessionModInfo *session_mod_info = static_cast<PJSipSessionModInfo*>(mInv->mod_data[mSessionModule->getModule().id]);
+            if (session_mod_info)
+            {
+                session_mod_info->updateSessionState(mInv);
+            }
+            lg(Debug) << "Replicating state on transaction state change to " << mTsxState;
+            mSessionModule->replicateState(dlg_mod_info, tsx_mod_info, session_mod_info);
+        }
+        else if (mEventType == PJSIP_EVENT_TIMER)
+        {
+            lg(Debug) << "Replicating state on transaction state change to " << mTsxState;
+            mSessionModule->replicateState(NULL, tsx_mod_info, NULL);
+        }
+        return Complete;
+    }
+
+    PJSipSessionModulePtr mSessionModule;
+    pjsip_transaction *mTsx;
+    pjsip_inv_session *mInv;
+    const int mEventType;
+    const int mTsxState;
+};
+
 void PJSipSessionModule::invOnTsxStateChanged(pjsip_inv_session *inv, pjsip_transaction *tsx, pjsip_event *e)
 {
     if (tsx->role == PJSIP_ROLE_UAS && tsx->state == PJSIP_TSX_STATE_TRYING &&
@@ -1242,45 +1301,10 @@ void PJSipSessionModule::invOnTsxStateChanged(pjsip_inv_session *inv, pjsip_tran
     //perform the proper state replication in the invOnStateChanged function. This can be done simply by calling this
     //function from there.
 
-    PJSipTransactionModInfo *tsx_mod_info = static_cast<PJSipTransactionModInfo *> (tsx->mod_data[mModule.id]);
-    // TODO: Determine if this is perfectly acceptable, since it occurs when the call is going bye bye
-    if (!tsx_mod_info)
-    {
-        return;
-    }
-    if (tsx->state != PJSIP_TSX_STATE_DESTROYED)
-    {
-        tsx_mod_info->updateTransactionState(tsx);
-    }
-    else
-    {
-        tsx_mod_info->mNeedsRemoval = true;
-    }
-    if (e->type == PJSIP_EVENT_TSX_STATE)
-    {
-        pjsip_dialog *dlg = pjsip_tsx_get_dlg(tsx);
-        PJSipDialogModInfo *dlg_mod_info = NULL;
-        if (dlg)
-        {
-            dlg_mod_info = static_cast<PJSipDialogModInfo*>(dlg->mod_data[mModule.id]);
-            if (dlg_mod_info)
-            {
-                dlg_mod_info->updateDialogState(dlg);
-            }
-        }
-        PJSipSessionModInfo *session_mod_info = static_cast<PJSipSessionModInfo*>(inv->mod_data[mModule.id]);
-        if (session_mod_info)
-        {
-            session_mod_info->updateSessionState(inv);
-        }
-        lg(Debug) << "Replicating state on transaction state change to " << tsx->state;
-        replicateState(dlg_mod_info, tsx_mod_info, session_mod_info);
-    }
-    else if (e->type == PJSIP_EVENT_TIMER)
-    {
-        lg(Debug) << "Replicating state on transaction state change to " << tsx->state;
-        replicateState(NULL, tsx_mod_info, NULL);
-    }
+    PJSipSessionModInfo *session_mod_info = static_cast<PJSipSessionModInfo*>(inv->mod_data[mModule.id]);
+    SipSessionPtr session = session_mod_info->getSessionPtr();
+
+    session->enqueueSessionWork(new TransactionStateOperation(this, tsx, inv, e->type, tsx->state));
 }
 
 void PJSipSessionModule::invOnRxOffer(pjsip_inv_session* inv, const pjmedia_sdp_session*)

commit e9d1aa434ba33120497c9dee97ef386f955753b3
Author: Mark Michelson <mmichelson at digium.com>
Date:   Mon May 16 10:33:18 2011 -0500

    Create the InvStateOperation class.
    
    It doesn't compile due to an itty bitty problem, but that should
    be cleared up once the transaction state operation is written.

diff --git a/src/PJSipModule.h b/src/PJSipModule.h
index df38f5a..5862d16 100644
--- a/src/PJSipModule.h
+++ b/src/PJSipModule.h
@@ -32,7 +32,7 @@ namespace SipSessionManager
 
 using namespace AsteriskSCF::SIP::V1;
 
-class PJSipModule
+class PJSipModule : public IceUtil::Shared
 {
 public:
     virtual pj_status_t load(pjsip_endpoint *endpoint) = 0;
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 85e4b4a..bf16b21 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -1087,109 +1087,135 @@ void PJSipSessionModule::handleInviteResponse(pjsip_inv_session* inv,
     session->enqueueSessionWork(new HandleInviteResponseOperation(respCode, inv->state, session));
 }
 
-void PJSipSessionModule::invOnStateChanged(pjsip_inv_session *inv, pjsip_event *event)
+class InviteStateOperation : public SipQueueableOperation
 {
-    if ((inv->state == PJSIP_INV_STATE_EARLY || inv->state == PJSIP_INV_STATE_CONNECTING) &&
-        event->type == PJSIP_EVENT_TSX_STATE &&
-        inv->role == PJSIP_ROLE_UAC)
-    {
-        //Received a 1XX or 2XX message in response to our initial outgoing INVITE.
-        handleInviteResponse(inv, event->body.tsx_state.src.rdata, inv->dlg);
-    }
-    if (inv->state == PJSIP_INV_STATE_DISCONNECTED)
+public:
+    InviteStateOperation(const PJSipSessionModulePtr& module, pjsip_inv_session* inv, const int eventType, const int invState, const std::string branch)
+        : mSessionModule(module), mInv(inv), mEventType(eventType), mInvState(invState), mEventBranch(branch) { }
+
+    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
     {
-        PJSipSessionModInfo *session_mod_info = (PJSipSessionModInfo*)inv->mod_data[mModule.id];
-        if (session_mod_info == 0)
-        {
-            return;
-        }
-        SipSessionPtr session = session_mod_info->getSessionPtr();
-        AsteriskSCF::SessionCommunications::V1::ResponseCodePtr response =
-            new AsteriskSCF::SessionCommunications::V1::ResponseCode();
-        if (inv->cause == 486)
-        {
-            response->isdnCode = 17;
-        }
-        else if (PJSIP_IS_STATUS_IN_CLASS(inv->cause, 500))
-        {
-            response->isdnCode = 34;
-        }
-        else
+        if (mInvState == PJSIP_INV_STATE_DISCONNECTED)
         {
-            // TODO: See what cause is on a normal call completion
-            response->isdnCode = 0;
-        }
-        std::vector<AsteriskSCF::SessionCommunications::V1::SessionListenerPrx> listeners = session->getListeners();
-        lg(Debug) << "Relating stopped state to " << listeners.size() << " listeners";
-        AsteriskSCF::SessionCommunications::V1::StoppedIndicationPtr stopped(new AsteriskSCF::SessionCommunications::V1::StoppedIndication());
-        stopped->response = response;
-        for (std::vector<AsteriskSCF::SessionCommunications::V1::SessionListenerPrx>::iterator listener =
-                 listeners.begin();
-             listener != listeners.end();
-             ++listener)
-        {
-            try
+            PJSipSessionModInfo *session_mod_info = (PJSipSessionModInfo*)mInv->mod_data[mSessionModule->getModule().id];
+            if (session_mod_info == 0)
+            {
+                return Complete;
+            }
+            SipSessionPtr session = session_mod_info->getSessionPtr();
+            AsteriskSCF::SessionCommunications::V1::ResponseCodePtr response =
+                new AsteriskSCF::SessionCommunications::V1::ResponseCode();
+            if (mInv->cause == 486)
+            {
+                response->isdnCode = 17;
+            }
+            else if (PJSIP_IS_STATUS_IN_CLASS(mInv->cause, 500))
+            {
+                response->isdnCode = 34;
+            }
+            else
             {
-                (*listener)->indicated(session->getSessionProxy(), stopped);
+                // TODO: See what cause is on a normal call completion
+                response->isdnCode = 0;
             }
-            catch (const Ice::Exception &ex)
+            std::vector<AsteriskSCF::SessionCommunications::V1::SessionListenerPrx> listeners = session->getListeners();
+            lg(Debug) << "Relating stopped state to " << listeners.size() << " listeners";
+            AsteriskSCF::SessionCommunications::V1::StoppedIndicationPtr stopped(new AsteriskSCF::SessionCommunications::V1::StoppedIndication());
+            stopped->response = response;
+            for (std::vector<AsteriskSCF::SessionCommunications::V1::SessionListenerPrx>::iterator listener =
+                     listeners.begin();
+                 listener != listeners.end();
+                 ++listener)
             {
-                lg(Error) << "Ice exception when attempting to relate stopped state: " << ex.what();
+                try
+                {
+                    (*listener)->indicated(session->getSessionProxy(), stopped);
+                }
+                catch (const Ice::Exception &ex)
+                {
+                    lg(Error) << "Ice exception when attempting to relate stopped state: " << ex.what();
+                }
+            }
+            session_mod_info->mNeedsRemoval = true;
+            pjsip_dialog *dlg = mInv->dlg;
+            PJSipDialogModInfo *dlg_mod_info = (PJSipDialogModInfo*) dlg->mod_data[mSessionModule->getModule().id];
+            if (dlg_mod_info)
+            {
+                dlg_mod_info->mNeedsRemoval = true;
+            }
+            lg(Debug) << "Replicating state on DISCONNECTED inv_state.";
+            mSessionModule->replicateState(dlg_mod_info, NULL, session_mod_info);
+            delete session_mod_info;
+            mInv->mod_data[mSessionModule->getModule().id] = 0;
+            if (dlg_mod_info)
+            {
+                delete dlg_mod_info;
+                dlg->mod_data[mSessionModule->getModule().id] = 0;
             }
         }
-        session_mod_info->mNeedsRemoval = true;
-        pjsip_dialog *dlg = inv->dlg;
-        PJSipDialogModInfo *dlg_mod_info = (PJSipDialogModInfo*) dlg->mod_data[mModule.id];
-        if (dlg_mod_info)
+        if (mEventType == PJSIP_EVENT_RX_MSG && mInvState == PJSIP_INV_STATE_CONFIRMED)
         {
-            dlg_mod_info->mNeedsRemoval = true;
+            //We received an ACK for our 2XX response.
+            //See comment in invOnTransactionStateChanged() for explanation of this.
+    
+            PJSipSessionModInfo *session_mod_info = static_cast<PJSipSessionModInfo*>(mInv->mod_data[mSessionModule->getModule().id]);
+            if (session_mod_info)
+            {
+                session_mod_info->updateSessionState(mInv);
+            }
+            mSessionModule->replicateState(NULL, NULL, session_mod_info);
+    
+            std::string invBranch(pj_strbuf(&mInv->invite_tsx->branch), pj_strlen(&mInv->invite_tsx->branch));
+            //Compare branches to see if this got handled by the transaction layer.
+            if (mInv->invite_tsx && mEventBranch != invBranch)
+            {
+                //Mismatched branch!
+                //XXX This needs to be changed to queue a transaction state change operation. That
+                //way, we won't require the entire event. Live with this not compiling at the moment.
+                mSessionModule->invOnTsxStateChanged(mInv, mInv->invite_tsx, event);
+            }
         }
-        lg(Debug) << "Replicating state on DISCONNECTED inv_state.";
-        replicateState(dlg_mod_info, NULL, session_mod_info);
-        delete session_mod_info;
-        inv->mod_data[mModule.id] = 0;
-        if (dlg_mod_info)
+        if (mEventType == PJSIP_EVENT_TSX_STATE && mInvState == PJSIP_INV_STATE_CALLING && mInv->role == PJSIP_ROLE_UAC)
         {
-            delete dlg_mod_info;
-            dlg->mod_data[mModule.id] = 0;
+            //We have sent an INVITE out. We need to set up the transaction and dialog structures
+            //to have the appropriate mod_data and initiate some state replication here as well.
+            //The inv_session's mod_info was set up in SipSession::start() because we had the SipSession
+            //information there.
+            PJSipDialogModInfo *dlg_mod_info = new PJSipDialogModInfo(mInv->dlg);
+            PJSipTransactionModInfo *tsx_mod_info = new PJSipTransactionModInfo(mInv->invite_tsx);
+            PJSipSessionModInfo *session_mod_info = static_cast<PJSipSessionModInfo *>(mInv->mod_data[mSessionModule->getModule().id]);
+            mInv->invite_tsx->mod_data[mSessionModule->getModule().id] = (void *) tsx_mod_info;
+            mInv->dlg->mod_data[mSessionModule->getModule().id] = (void *) dlg_mod_info;
+            dlg_mod_info->mDialogState->mSessionId = session_mod_info->mSessionState->mSessionId;
+            tsx_mod_info->mTransactionState->mSessionId = session_mod_info->mSessionState->mSessionId;
+            lg(Debug) << "Replicating state on new outbound INVITE.";
+            mSessionModule->replicateState(dlg_mod_info, tsx_mod_info, session_mod_info);
         }
+        return Complete;
     }
-    if (event->type == PJSIP_EVENT_RX_MSG && inv->state == PJSIP_INV_STATE_CONFIRMED)
-    {
-        //We received an ACK for our 2XX response.
-        //See comment in invOnTransactionStateChanged() for explanation of this.
 
-        PJSipSessionModInfo *session_mod_info = static_cast<PJSipSessionModInfo*>(inv->mod_data[mModule.id]);
-        if (session_mod_info)
-        {
-            session_mod_info->updateSessionState(inv);
-        }
-        replicateState(NULL, NULL, session_mod_info);
+    PJSipSessionModulePtr mSessionModule;
+    pjsip_inv_session* mInv;
+    const int mEventType;
+    const int mInvState;
+    const std::string mEventBranch;
+};
 
-        //Compare branches to see if this got handled by the transaction layer.
-        if (inv->invite_tsx &&
-                pj_strcmp(&event->body.rx_msg.rdata->msg_info.via->branch_param, &inv->invite_tsx->branch) != 0)
-        {
-            //Mismatched branch!
-            invOnTsxStateChanged(inv, inv->invite_tsx, event);
-        }
-    }
-    if (event->type == PJSIP_EVENT_TSX_STATE && inv->state == PJSIP_INV_STATE_CALLING && inv->role == PJSIP_ROLE_UAC)
+void PJSipSessionModule::invOnStateChanged(pjsip_inv_session *inv, pjsip_event *event)
+{
+    if ((inv->state == PJSIP_INV_STATE_EARLY || inv->state == PJSIP_INV_STATE_CONNECTING) &&
+        event->type == PJSIP_EVENT_TSX_STATE &&
+        inv->role == PJSIP_ROLE_UAC)
     {
-        //We have sent an INVITE out. We need to set up the transaction and dialog structures
-        //to have the appropriate mod_data and initiate some state replication here as well.
-        //The inv_session's mod_info was set up in SipSession::start() because we had the SipSession
-        //information there.
-        PJSipDialogModInfo *dlg_mod_info = new PJSipDialogModInfo(inv->dlg);
-        PJSipTransactionModInfo *tsx_mod_info = new PJSipTransactionModInfo(inv->invite_tsx);
-        PJSipSessionModInfo *session_mod_info = static_cast<PJSipSessionModInfo *>(inv->mod_data[mModule.id]);
-        inv->invite_tsx->mod_data[mModule.id] = (void *) tsx_mod_info;
-        inv->dlg->mod_data[mModule.id] = (void *) dlg_mod_info;
-        dlg_mod_info->mDialogState->mSessionId = session_mod_info->mSessionState->mSessionId;
-        tsx_mod_info->mTransactionState->mSessionId = session_mod_info->mSessionState->mSessionId;
-        lg(Debug) << "Replicating state on new outbound INVITE.";
-        replicateState(dlg_mod_info, tsx_mod_info, session_mod_info);
+        //Received a 1XX or 2XX message in response to our initial outgoing INVITE.
+        handleInviteResponse(inv, event->body.tsx_state.src.rdata, inv->dlg);
     }
+    
+    PJSipSessionModInfo *session_mod_info = (PJSipSessionModInfo*)inv->mod_data[mModule.id];
+    SipSessionPtr session = session_mod_info->getSessionPtr();
+
+    std::string branch(pj_strbuf(&event->body.rx_msg.rdata->msg_info.via->branch_param), pj_strlen(&event->body.rx_msg.rdata->msg_info.via->branch_param));
+    session->enqueueSessionWork(new InviteStateOperation(this, inv, event->type, inv->state, branch));
 }
 
 void PJSipSessionModule::invOnNewSession(pjsip_inv_session*, pjsip_event*)
diff --git a/src/PJSipSessionModule.h b/src/PJSipSessionModule.h
index fe24470..9d9f4a9 100644
--- a/src/PJSipSessionModule.h
+++ b/src/PJSipSessionModule.h
@@ -125,6 +125,8 @@ private:
     AsteriskSCF::System::ThreadPool::V1::PoolListenerPtr mPoolListener;
 };
 
+typedef IceUtil::Handle<PJSipSessionModule> PJSipSessionModulePtr;
+
 class SipQueueableOperation : virtual public AsteriskSCF::System::WorkQueue::V1::SuspendableWork
 {
 public:

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


-- 
asterisk-scf/integration/sip.git



More information about the asterisk-scf-commits mailing list