[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
Thu May 12 15:02:19 CDT 2011
branch "threading" has been updated
via 275aecd899a44502b0a4f76eab747691bd92af5f (commit)
from 78e5e7f41cc406ab6fd735cd3bc2684f2ededd38 (commit)
Summary of changes:
src/PJSipSessionModule.cpp | 459 ++++++++++++++++++++++++++------------------
src/PJSipSessionModule.h | 24 +++
2 files changed, 298 insertions(+), 185 deletions(-)
- Log -----------------------------------------------------------------
commit 275aecd899a44502b0a4f76eab747691bd92af5f
Author: Mark Michelson <mmichelson at digium.com>
Date: Thu May 12 14:59:29 2011 -0500
Adding content just so it doesn't get lost.
My first attempt at queueing an operation that originates from PJSIP.
I'm starting with a complex one that makes AMI calls.
This doesn't come close to compiling.
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 32ed923..19a6c81 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -100,55 +100,6 @@ private:
};
typedef IceUtil::Handle<RouteSessionCallback> RouteSessionCallbackPtr;
-class ConnectBridgedSessionsCallback : public IceUtil::Shared
-{
-public:
- ConnectBridgedSessionsCallback(pjsip_inv_session *inv_session,
- pjsip_tx_data *tdata,
- pjsip_transaction *tsx,
- const SipSessionPtr& session,
- const SipSessionPtr& otherSession,
- const std::string& operationId)
- : mInvSession(inv_session),
- mTData(tdata),
- mTsx(tsx),
- mSession(session),
- mOtherSession(otherSession),
- mOperationId(operationId)
-
- {
- }
-
- void callback(const Ice::AsyncResultPtr &r)
- {
- SessionRouterPrx router = SessionRouterPrx::uncheckedCast(r->getProxy());
- try
- {
- router->end_connectBridgedSessions(r);
- }
- catch (const std::exception &e)
- {
- lg(Debug) << "ConnectBridgedSessionsCallback sending 400 due to exception: " << e.what();
- pjsip_dlg_modify_response(mInvSession->dlg, mTData, 400, NULL);
- pjsip_dlg_send_response(mInvSession->dlg, mTsx, mTData);
- return;
- }
- pjsip_dlg_send_response(mInvSession->dlg, mTsx, mTData);
-
- Ice::Current current;
- lg(Debug) << "ConnectBridgedSessionsCallback calling session->stop(). ";
- mSession->stop(new ResponseCode(16), current);
- }
-private:
- pjsip_inv_session *mInvSession;
- pjsip_tx_data *mTData;
- pjsip_transaction *mTsx;
- SipSessionPtr mSession;
- SipSessionPtr mOtherSession;
- std::string mOperationId;
-};
-
-typedef IceUtil::Handle<ConnectBridgedSessionsCallback> ConnectBridgedSessionsCallbackPtr;
class ConnectBridgedSessionsWithDestinationCallback : public IceUtil::Shared
{
@@ -491,6 +442,9 @@ void PJSipSessionModule::handleNewInvite(pjsip_rx_data *rdata)
//XXX Put caller identification code in here!
+ //We handle most of the processing here synchronously since
+ //at this point there is no associated session, plus the lead-up
+ //to creating a session is not especially intensive.
pjsip_tx_data *tdata = NULL;
unsigned options = PJSIP_INV_SUPPORT_100REL;
@@ -559,6 +513,10 @@ void PJSipSessionModule::handleNewInvite(pjsip_rx_data *rdata)
pjsip_timer_setting_default(&session_timer_settings);
pjsip_timer_init_session(inv_session, &session_timer_settings);
+ //XXX This marks the last time we actually make use of the
+ //rdata in this function. The times past this point are to get
+ //data from within the rdata. We can just as easily get that
+ //earlier.
if (pjsip_inv_initial_answer(inv_session, rdata, 100, NULL, NULL, &tdata) != PJ_SUCCESS)
{
lg(Warning) << "Failed to create 100 Trying response";
@@ -609,6 +567,16 @@ void PJSipSessionModule::handleNewInvite(pjsip_rx_data *rdata)
lg(Debug) << "Call is destined for " << destination;
}
+ //XXX This is the point where it would be nice to just return. The SessionWork is created
+ //in the createSession() method at the moment, which actually makes this a tad tough. What
+ //would be better would be to create the SessionWork here. Then we could queue the
+ //createSession operation onto it and just return here. Then, when the createSession()
+ //operation runs, when it needs to call out to the media component to create the media
+ //session, it can use AMI to call out and return "Suspended." Then the AMI callback can
+ //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".
+
SipSessionPtr session;
try
{
@@ -657,176 +625,282 @@ void PJSipSessionModule::handleNewInvite(pjsip_rx_data *rdata)
}
}
-void PJSipSessionModule::handleRefer(pjsip_inv_session *inv, pjsip_rx_data *rdata)
+class HandleReferOperation : public SuspendableWork, public IceUtil::Shared
{
- const pj_str_t str_refer_to = { (char*)"Refer-To", 8 };
- pjsip_generic_string_hdr *refer_to =
- static_cast<pjsip_generic_string_hdr *>(pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_refer_to, NULL));
-
- lg(Debug) << "Handling a REFER";
- if (!refer_to)
+public:
+ HandleReferOperation(
+ pjsip_inv_session *inv,
+ pjsip_transaction *tsx,
+ pjsip_tx_data *tdata,
+ pjsip_sip_uri *target_sip_uri,
+ const SipSessionPtr& session,
+ const SmartProxy<SessionRouterPrx>& sessionRouter)
+ : mState(Initial), mInv(inv), mTsx(tsx), mTdata(tdata),
+ mTargetSipUri(target_sip_uri), mSession(session), mSessionRouter(sessionRouter) { }
+
+ SuspendableWorkResult execute(const SuspendableWorkListenerPtr& workListener)
{
- // Uh... so they didn't tell us where to REFER this to... yeah no
- lg(Debug) << "handleRefer() sending 400 due to no refer_to. ";
- pjsip_dlg_respond(inv->dlg, rdata, 400, NULL, NULL, NULL);
- return;
+ switch (mState)
+ {
+ case Initial:
+ return processRefer(workListener);
+ case CalledBack:
+ return processRoutingResponse(workListener);
+ default:
+ lg(Error) << "We're in a bad state here...and I don't mean South Dakota!";
+ return Complete;
+ }
}
- // TODO: Add support for subscription
-
- // TODO: Provide method to send back suitable response
-
- // Now parse the URI to get the actual target they want to refer to
- pjsip_uri *target_uri = static_cast<pjsip_uri *>(pjsip_parse_uri(inv->dlg->pool, refer_to->hvalue.ptr, refer_to->hvalue.slen, 0));
-
- // We only support SIP URIs, anything else is rubbish to us
- if (!PJSIP_URI_SCHEME_IS_SIP(target_uri) && !PJSIP_URI_SCHEME_IS_SIPS(target_uri))
+ void changeState()
{
- // TODO: Place proper response code in here
- lg(Debug) << "handleRefer() sending 400 due to non-SIP URI. ";
- pjsip_dlg_respond(inv->dlg, rdata, 400, NULL, NULL, NULL);
- return;
+ ++mState;
}
- pjsip_sip_uri *target_sip_uri = (pjsip_sip_uri *)pjsip_uri_get_uri(target_uri);
-
- // Determine if this is a blind transfer or an attended transfer
- pj_str_t replaces = pj_str((char*)"Replaces");
- pjsip_param *replaces_param = pjsip_param_find(&target_sip_uri->other_param, &replaces);
-
- if (!replaces_param)
+ SuspendableWorkResult processRoutingResponse(workListener)
{
- replaces_param = pjsip_param_find(&target_sip_uri->header_param, &replaces);
+ assert(mAsyncResult);
+ SessionRouterPrx router = SessionRouterPrx::uncheckedCast(r->getProxy());
+ try
+ {
+ router->end_connectBridgedSessions(r);
+ }
+ catch (const std::exception &e)
+ {
+ lg(Debug) << "ConnectBridgedSessionsCallback sending 400 due to exception: " << e.what();
+ pjsip_dlg_modify_response(mInv->dlg, mTData, 400, NULL);
+ pjsip_dlg_send_response(mInv->dlg, mTsx, mTData);
+ return;
+ }
+ pjsip_dlg_send_response(mInv->dlg, mTsx, mTData);
+
+ Ice::Current current;
+ lg(Debug) << "ConnectBridgedSessionsCallback calling session->stop(). ";
+ mSession->stop(new ResponseCode(16), current);
}
- if (replaces_param)
+ SuspendableWorkResult processRefer(const SuspendableWorKListenerPtr& workListener)
{
- pj_str_t to_tag = pj_str((char*)"To-tag");
- pj_str_t from_tag = pj_str((char*)"From-tag");
- pjsip_param *to_tag_param = pjsip_param_find(&target_sip_uri->other_param, &to_tag);
- pjsip_param *from_tag_param = pjsip_param_find(&target_sip_uri->other_param, &from_tag);
- pjsip_dialog *other_dlg = NULL;
+ // Determine if this is a blind transfer or an attended transfer
+ pj_str_t replaces = pj_str((char*)"Replaces");
+ pjsip_param *replaces_param = pjsip_param_find(&mTargetSipUri->other_param, &replaces);
- if (to_tag_param && from_tag_param)
+ if (!replaces_param)
{
- other_dlg = pjsip_ua_find_dialog(&replaces_param->value, &to_tag_param->value, &from_tag_param->value,
- PJ_TRUE);
+ replaces_param = pjsip_param_find(&mTargetSipUri->header_param, &replaces);
}
- else
+
+ if (replaces_param)
{
- // 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(&replaces_param->value),
- pj_strlen(&replaces_param->value));
- size_t from_tag_pos = replaces_value_tmp.find(";from-tag=");
- size_t to_tag_pos = replaces_value_tmp.find(";to-tag=");
-
- if (from_tag_pos == std::string::npos || to_tag_pos == std::string::npos)
+ pj_str_t to_tag = pj_str((char*)"To-tag");
+ pj_str_t from_tag = pj_str((char*)"From-tag");
+ pjsip_param *to_tag_param = pjsip_param_find(&mTargetSipUri->other_param, &to_tag);
+ pjsip_param *from_tag_param = pjsip_param_find(&mTargetSipUri->other_param, &from_tag);
+ pjsip_dialog *other_dlg = NULL;
+
+ if (to_tag_param && from_tag_param)
{
- lg(Debug) << "handleRefer() sending 400 due to From or To missing. ";
- pjsip_dlg_respond(inv->dlg, rdata, 400, NULL, NULL, NULL);
- return;
+ other_dlg = pjsip_ua_find_dialog(&replaces_param->value, &to_tag_param->value, &from_tag_param->value,
+ PJ_TRUE);
}
+ 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(&replaces_param->value),
+ pj_strlen(&replaces_param->value));
+ size_t from_tag_pos = replaces_value_tmp.find(";from-tag=");
+ size_t to_tag_pos = replaces_value_tmp.find(";to-tag=");
+
+ if (from_tag_pos == std::string::npos || to_tag_pos == std::string::npos)
+ {
+ 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;
+ }
- std::string to_tag_value = replaces_value_tmp.substr(to_tag_pos + 8, from_tag_pos - to_tag_pos - 8);
- std::string from_tag_value = replaces_value_tmp.substr(from_tag_pos + 10);
- std::string replaces_value = replaces_value_tmp.substr(0, to_tag_pos);
-
- pj_str_t to_tag_str = pj_str((char*)to_tag_value.c_str());
- pj_str_t from_tag_str = pj_str((char*)from_tag_value.c_str());
- pj_str_t replaces_tag_str = pj_str((char*)replaces_value.c_str());
+ std::string to_tag_value = replaces_value_tmp.substr(to_tag_pos + 8, from_tag_pos - to_tag_pos - 8);
+ std::string from_tag_value = replaces_value_tmp.substr(from_tag_pos + 10);
+ std::string replaces_value = replaces_value_tmp.substr(0, to_tag_pos);
- other_dlg = pjsip_ua_find_dialog(&replaces_tag_str, &to_tag_str, &from_tag_str, PJ_TRUE);
- }
+ pj_str_t to_tag_str = pj_str((char*)to_tag_value.c_str());
+ pj_str_t from_tag_str = pj_str((char*)from_tag_value.c_str());
+ pj_str_t replaces_tag_str = pj_str((char*)replaces_value.c_str());
- if (!other_dlg)
- {
- lg(Debug) << "handleRefer() sending PJSIP_SC_CALL_TSX_DOES_NOT_EXIST due to no other_dlg. ";
- pjsip_dlg_respond(inv->dlg, rdata, PJSIP_SC_CALL_TSX_DOES_NOT_EXIST, NULL, NULL, NULL);
- return;
- }
+ other_dlg = pjsip_ua_find_dialog(&replaces_tag_str, &to_tag_str, &from_tag_str, PJ_TRUE);
+ }
- pjsip_inv_session *other_inv = pjsip_dlg_get_inv_session(other_dlg);
+ if (!other_dlg)
+ {
+ lg(Debug) << "handleRefer() sending PJSIP_SC_CALL_TSX_DOES_NOT_EXIST due to no other_dlg. ";
+ pjsip_dlg_modify_response(mInv->dlg, mTData, PJSIP_SC_CALL_TSX_DOES_NOT_EXIST, NULL);
+ pjsip_dlg_send_response(mInv->dlg, mTsx, mTData);
+ return Complete;
+ }
- if (!other_inv)
- {
- lg(Debug) << "handleRefer() sending PJSIP_SC_CALL_TSX_DOES_NOT_EXIST due to no other_inv. ";
- pjsip_dlg_respond(inv->dlg, rdata, PJSIP_SC_CALL_TSX_DOES_NOT_EXIST, NULL, NULL, NULL);
- pjsip_dlg_dec_lock(other_dlg);
- return;
- }
+ pjsip_inv_session *other_inv = pjsip_dlg_get_inv_session(other_dlg);
- if (other_inv->state >= PJSIP_INV_STATE_DISCONNECTED)
- {
- lg(Debug) << "handleRefer() sending PJSIP_SC_DECLINE due to state > PJSIP_INV_STATE_DISCONNECTED. ";
+ if (!other_inv)
+ {
+ lg(Debug) << "handleRefer() sending PJSIP_SC_CALL_TSX_DOES_NOT_EXIST due to no other_inv. ";
+ pjsip_dlg_modify_response(mInv->dlg, mTData, PJSIP_SC_CALL_TSX_DOES_NOT_EXIST, NULL);
+ pjsip_dlg_send_response(mInv->dlg, mTsx, mTData);
+ pjsip_dlg_dec_lock(other_dlg);
+ return Complete;
+ }
- pjsip_dlg_respond(inv->dlg, rdata, PJSIP_SC_DECLINE, NULL, NULL, NULL);
- pjsip_dlg_dec_lock(other_dlg);
- return;
- }
+ if (other_inv->state >= PJSIP_INV_STATE_DISCONNECTED)
+ {
+ lg(Debug) << "handleRefer() sending PJSIP_SC_DECLINE due to state > PJSIP_INV_STATE_DISCONNECTED. ";
- if (other_inv->state <= PJSIP_INV_STATE_EARLY && other_inv->role != PJSIP_ROLE_UAC)
- {
- lg(Debug) << "handleRefer() sending PJSIP_SC_CALL_TSX_DOES_NOT_EXIST due to other_inv->state < PJSIP_INV_STATE_EARLY and role not UAC. ";
+ pjsip_dlg_modify_response(mInv->dlg, mTData, PJSIP_SC_DECLINE, NULL);
+ pjsip_dlg_send_response(mInv->dlg, mTsx, mTData);
+ pjsip_dlg_dec_lock(other_dlg);
+ return Complete;
+ }
- pjsip_dlg_respond(inv->dlg, rdata, PJSIP_SC_CALL_TSX_DOES_NOT_EXIST, NULL, NULL, NULL);
- pjsip_dlg_dec_lock(other_dlg);
- return;
- }
+ if (other_inv->state <= PJSIP_INV_STATE_EARLY && other_inv->role != PJSIP_ROLE_UAC)
+ {
+ lg(Debug) << "handleRefer() sending PJSIP_SC_CALL_TSX_DOES_NOT_EXIST due to other_inv->state < PJSIP_INV_STATE_EARLY and role not UAC. ";
- PJSipSessionModInfo *session_mod_info = (PJSipSessionModInfo*)inv->mod_data[mModule.id];
- SipSessionPtr session = session_mod_info->getSessionPtr();
+ pjsip_dlg_modify_response(mInv->dlg, mTData, PJSIP_SC_CALL_TSX_DOES_NOT_EXIST, NULL);
+ pjsip_dlg_send_response(mInv->dlg, mTsx, mTData);
+ pjsip_dlg_dec_lock(other_dlg);
+ return Complete;
+ }
- PJSipSessionModInfo *other_session_mod_info = (PJSipSessionModInfo*)other_inv->mod_data[mModule.id];
- SipSessionPtr other_session = other_session_mod_info->getSessionPtr();
+ PJSipSessionModInfo *other_session_mod_info = (PJSipSessionModInfo*)other_inv->mod_data[mModule.id];
+ SipSessionPtr other_session = other_session_mod_info->getSessionPtr();
- try
- {
- pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata);
- pjsip_tx_data *tdata;
- pjsip_dlg_create_response(inv->dlg, rdata, 200, NULL, &tdata);
- std::string operationId = ::IceUtil::generateUUID();
- ConnectBridgedSessionsCallbackPtr cb(new ConnectBridgedSessionsCallback(inv, tdata, tsx, session, other_session, operationId));
- Ice::CallbackPtr d = Ice::newCallback(cb, &ConnectBridgedSessionsCallback::callback);
+ try
+ {
+ std::string operationId = ::IceUtil::generateUUID();
+ SipAMICallbackPtr cb(new SipAMICallback(workListener, this));
+ Ice::CallbackPtr d = Ice::newCallback(cb, &ConnectBridgedSessionsCallback::callback);
- lg(Debug) << "handleRefer() calling router connectBridgedSessions(). ";
- mSessionRouter->begin_connectBridgedSessions(operationId, session->getSessionProxy(), other_session->getSessionProxy(), d);
+ lg(Debug) << "handleRefer() calling router connectBridgedSessions(). ";
+ mSessionRouter->begin_connectBridgedSessions(operationId, mSession->getSessionProxy(), other_session->getSessionProxy(), d);
+ return Suspended;
+ }
+ catch (const Ice::CommunicatorDestroyedException &)
+ {
+ lg(Debug) << "handleRefer() sending 503 due to communicator destruction";
+ pjsip_dlg_respond(mInv->dlg, rdata, 503, NULL, NULL, NULL);
+ return Complete;
+ }
+ pjsip_dlg_dec_lock(other_dlg);
}
- catch (const Ice::CommunicatorDestroyedException &)
+ else
{
- lg(Debug) << "handleRefer() sending 503 due to communicator destruction";
- pjsip_dlg_respond(inv->dlg, rdata, 503, NULL, NULL, NULL);
- return;
+ std::string target = std::string(pj_strbuf(&mTargetSipUri->user), pj_strlen(&mTargetSipUri->user));
+
+ // Now that we have the target user we can pass this into routing and go on our marry way
+ try
+ {
+ std::string operationId = ::IceUtil::generateUUID();
+ PJSipSessionModInfo *session_mod_info = (PJSipSessionModInfo*)mInv->mod_data[mModule.id];
+ SipSessionPtr session = session_mod_info->getSessionPtr();
+ SipAMICallbackPtr cb(new SipAMICallback(workListener, this));
+ Ice::CallbackPtr d = Ice::newCallback(cb, &ConnectBridgedSessionsWithDestinationCallback::callback);
+
+ lg(Debug) << "handleRefer() calling router connectBridgedSessionsWithDestination(). ";
+ mSessionRouter->begin_connectBridgedSessionsWithDestination(operationId, session->getSessionProxy(), target, d);
+ return Suspended;
+ }
+ catch (const Ice::CommunicatorDestroyedException &)
+ {
+ lg(Debug) << "handleRefer() sending 503 due to communicator destruction";
+ pjsip_dlg_respond(mInv->dlg, rdata, 503, NULL, NULL, NULL);
+ return Complete;
+ }
}
- pjsip_dlg_dec_lock(other_dlg);
- }
- else
+ };
+
+ enum states
{
- std::string target = std::string(pj_strbuf(&target_sip_uri->user), pj_strlen(&target_sip_uri->user));
+ Initial,
+ CalledBack,
+ } mState;
+ /**
+ * The INVITE session, which contains the dialog on which the
+ * REFER was received.
+ */
+ pjsip_inv_session *mInv;
+ /**
+ * The REFER transaction
+ */
+ pjsip_transaction *mTsx;
+ /**
+ * The transmission data for our REFER response. We set this
+ * up to default to a 200 OK response and alter it if necessary.
+ */
+ pjsip_tx_data *mTdata;
+ /**
+ * The SIP URI from the Refer-To header in the REFER request.
+ */
+ pjsip_sip_uri *mTargetSipUri;
+ /**
+ * The SipSession on which this work is executed
+ */
+ SipSessionPtr mSession;
+ /**
+ * Session router...nothing more to say really
+ */
+ SmartProxy<SessionRouterPrx> mSessionRouter;
+ /**
+ * The result of any AMI calls we make
+ */
+ Ice::AsyncResultPtr mAsyncResult;
+};
- // Now that we have the target user we can pass this into routing and go on our marry way
- try
- {
- std::string operationId = ::IceUtil::generateUUID();
- PJSipSessionModInfo *session_mod_info = (PJSipSessionModInfo*)inv->mod_data[mModule.id];
- SipSessionPtr session = session_mod_info->getSessionPtr();
- pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata);
- pjsip_tx_data *tdata;
- pjsip_dlg_create_response(inv->dlg, rdata, 200, NULL, &tdata);
- ConnectBridgedSessionsWithDestinationCallbackPtr cb(
- new ConnectBridgedSessionsWithDestinationCallback(inv, tdata, tsx, session, target, operationId));
- Ice::CallbackPtr d = Ice::newCallback(cb, &ConnectBridgedSessionsWithDestinationCallback::callback);
-
- lg(Debug) << "handleRefer() calling router connectBridgedSessionsWithDestination(). ";
- mSessionRouter->begin_connectBridgedSessionsWithDestination(operationId, session->getSessionProxy(), target, d);
- }
- catch (const Ice::CommunicatorDestroyedException &)
- {
- lg(Debug) << "handleRefer() sending 503 due to communicator destruction";
- pjsip_dlg_respond(inv->dlg, rdata, 503, NULL, NULL, NULL);
- return;
- }
+void PJSipSessionModule::handleRefer(pjsip_inv_session *inv, pjsip_rx_data *rdata)
+{
+ //rdata structures are not safe to shallow copy to a queuable operation. Get
+ //what we need out of it.
+ const pj_str_t str_refer_to = { (char*)"Refer-To", 8 };
+ pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata);
+ pjsip_generic_string_hdr *refer_to =
+ static_cast<pjsip_generic_string_hdr *>(pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_refer_to, NULL));
+
+ lg(Debug) << "Handling a REFER";
+ if (!refer_to)
+ {
+ // Uh... so they didn't tell us where to REFER this to... yeah no
+ lg(Debug) << "handleRefer() sending 400 due to no refer_to. ";
+ pjsip_dlg_respond(inv->dlg, rdata, 400, NULL, NULL, NULL);
+ return;
+ }
+
+ // TODO: Add support for subscription
+
+ // TODO: Provide method to send back suitable response
+
+ // Now parse the URI to get the actual target they want to refer to
+ //
+ // Parsing the URI allocates memory in the dialog's pool, thus allowing a
+ // safe shallow copy to a queueable operation.
+ pjsip_uri *target_uri = static_cast<pjsip_uri *>(pjsip_parse_uri(inv->dlg->pool, refer_to->hvalue.ptr, refer_to->hvalue.slen, 0));
+
+ // We only support SIP URIs, anything else is rubbish to us
+ if (!PJSIP_URI_SCHEME_IS_SIP(target_uri) && !PJSIP_URI_SCHEME_IS_SIPS(target_uri))
+ {
+ // TODO: Place proper response code in here
+ lg(Debug) << "handleRefer() sending 400 due to non-SIP URI. ";
+ pjsip_dlg_respond(inv->dlg, rdata, 400, NULL, NULL, NULL);
+ return;
}
+
+ pjsip_sip_uri *target_sip_uri = (pjsip_sip_uri *)pjsip_uri_get_uri(target_uri);
+
+ PJSipSessionModInfo *session_mod_info = (PJSipSessionModInfo*) inv->mod_data[mModule.id];
+ SipSessionPtr session = session_mod_info->getSessionPtr();
+
+ //Create our initial response that we can modify in the queueable operation.
+ pjsip_tx_data *tdata;
+ pjsip_dlg_create_response(inv->dlg, rdata, 200, NULL, &tdata);
+
+ session->enqueueSessionWork(new HandleReferOperation(inv, tsx, tdata, target_sip_uri, session, mSessionRouter));
}
pj_bool_t PJSipSessionModule::on_rx_request(pjsip_rx_data *rdata)
@@ -854,7 +928,7 @@ pj_bool_t PJSipSessionModule::on_rx_request(pjsip_rx_data *rdata)
break;
}
default:
- pjsip_endpt_respond_stateless(mEndpoint, rdata, 405, NULL, NULL, NULL);
+ pjsip_endpt_respond_stateless(mEndpoint, rdata, 405, NULL, NULL, NULL);
break;
}
@@ -1318,6 +1392,20 @@ void PJSipSessionModuleThreadPoolListener::queueEmptied(const PoolPtr& pool)
pool->setSize(0);
}
+class SipSessionSuspendableWorkListener : public SuspendableWorkListener
+{
+public:
+ SipSessionSuspendableWorkListener(const QueueListenerPtr& queueListener)
+ : mQueueListener(queueListener) { }
+
+ void workResumable()
+ {
+ mQueueListener->workResumable();
+ }
+
+ QueueListenerPtr mQueueListener;
+};
+
SessionWork::SessionWork(const QueuePtr& queue)
: mThreadPoolQueue(queue),
mInternalQueue(new SuspendableWorkQueue(this)) { }
@@ -1343,7 +1431,8 @@ void SessionWork::emptied()
void SessionWork::execute()
{
- while(mInternalQueue->executeWork());
+ SuspendableWorkListenerPtr listener(new SipSessionSuspendableWorkListener(this));
+ while(mInternalQueue->executeWork(listener));
}
void SessionWork::enqueueWork(const SuspendableWorkPtr& work)
diff --git a/src/PJSipSessionModule.h b/src/PJSipSessionModule.h
index 75706e3..dbbd95a 100644
--- a/src/PJSipSessionModule.h
+++ b/src/PJSipSessionModule.h
@@ -26,6 +26,7 @@
#include <AsteriskSCF/SmartProxy.h>
#include <AsteriskSCF/System/Component/ReplicaIf.h>
#include <AsteriskSCF/System/ThreadPool/ThreadPoolIf.h>
+#include <AsteriskSCF/System/WorkQueue/WorkQueueIf.h>
#include "SipStateReplicator.h"
#include "SipSession.h"
@@ -124,5 +125,28 @@ private:
AsteriskSCF::System::ThreadPool::V1::PoolListenerPtr mPoolListener;
};
+template <class T>
+class SipAMICallback : public IceUtil::Shared
+{
+public:
+ SipAMICallback(
+ const AsteriskSCF::System::WorkQueue::V1::SuspendableWorkListenerPtr& listener,
+ const T& operation)
+ : mListener(listener), mOperation(operation)
+ {
+ }
+
+ void callback(const Ice::AsyncResultPtr &r)
+ {
+ mOperation->mAsyncResult = r;
+ mOperation->changeState();
+ mListener->workResumable();
+ }
+
+private:
+ AsteriskSCF::System::WorkQueue::V1::SuspendableWorkListenerPtr& mListener;
+ T& mOperation;
+};
+
}; //end namespace SipSessionManager
}; //end namespace AsteriskSCF
-----------------------------------------------------------------------
--
asterisk-scf/integration/sip.git
More information about the asterisk-scf-commits
mailing list