[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