[asterisk-scf-commits] asterisk-scf/integration/sip.git branch "telephone-events" updated.
Commits to the Asterisk SCF project code repositories
asterisk-scf-commits at lists.digium.com
Wed Jul 6 11:40:47 CDT 2011
branch "telephone-events" has been updated
via a815ad12e32d57dc4ece7488fe72ce0e82f5e4d9 (commit)
from bd25df69bafa9d87b5c427a11422fc0c0c0fc5bd (commit)
Summary of changes:
src/PJSipSessionModule.cpp | 117 ++++++++++++++++++++++++++++++++++++++++---
1 files changed, 108 insertions(+), 9 deletions(-)
- Log -----------------------------------------------------------------
commit a815ad12e32d57dc4ece7488fe72ce0e82f5e4d9
Author: Mark Michelson <mmichelson at digium.com>
Date: Wed Jul 6 11:34:38 2011 -0500
Queue a DTMF INFO operation, add error checking to handleInfo.
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index ff47c0e..066bfc9 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -912,6 +912,34 @@ void PJSipSessionModule::handleRefer(pjsip_inv_session *inv, pjsip_rx_data *rdat
enqueueSessionWork(new HandleReferOperation(inv, tsx, tdata, replaces_param, to_tag_param, from_tag_param, target, session, mSessionRouter, mModule.id), inv);
}
+class HandleInfoDTMFOperation : public SipQueueableOperation
+{
+public:
+ HandleInfoDTMFOperation(
+ pjsip_inv_session *inv,
+ pjsip_transaction *tsx,
+ pjsip_tx_data *tdata,
+ char dtmf,
+ int duration)
+ : mInv(inv), mTsx(tsx), mTdata(tdata), mDTMF(dtmf), mDuration(duration) { }
+
+ SuspendableWorkResult initial(const SuspendableWorkListenerPtr& workListener)
+ {
+ //XXX We need to send an indicated() operation to our session listeners.
+ //There's not a DTMF indication defined at the moment, so I'll withhold
+ //that until I have defined such a method.
+
+ pjsip_dlg_send_response(mInv->dlg, mTsx, mTdata);
+ }
+
+private:
+ pjsip_inv_session *mInv;
+ pjsip_transaction *mTsx;
+ pjsip_tx_data *mTdata;
+ char mDTMF;
+ int mDuration;
+};
+
bool PJSipSessionModule::isDTMF(pjsip_rx_data *rdata)
{
// We should determine how to handle matters based on the "Info-Package" header,
@@ -929,9 +957,11 @@ bool PJSipSessionModule::isDTMF(pjsip_rx_data *rdata)
pj_cstr(&dtmf, "dtmf");
if (info_package && !pj_strcmp(&info_package->hvalue, &dtmf))
{
+ lg(Debug) << "Info-Package header suggests DTMF";
return true;
}
+ lg(Debug) << "No Info-Package header. Checking Content-Type";
//No biggie. I just said that not many are actually going to use Info-Package.
//Check if the content-type is "application/dtmf-relay"
pj_str_t application;
@@ -941,39 +971,93 @@ bool PJSipSessionModule::isDTMF(pjsip_rx_data *rdata)
if (!pj_strcmp(&rdata->msg_info.ctype->media.type, &application) &&
!pj_strcmp(&rdata->msg_info.ctype->media.subtype, &dtmf_relay))
{
+ lg(Debug) << "Content-Type is application/dtmf-relay";
return true;
}
return false;
}
+class DTMFInfoException : public std::exception
+{
+public:
+ DTMFInfoException(const std::string& msg)
+ : mMsg(msg) { }
+
+ ~DTMFInfoException() throw() { }
+
+ const char *what() const throw()
+ {
+ return mMsg.c_str();
+ }
+private:
+ const std::string mMsg;
+};
+
char PJSipSessionModule::getDTMFInfoSignal(pjsip_msg_body *body)
{
char *data = static_cast<char *>(body->data);
std::string dataStr(data, body->len);
+ std::string signalStr("Signal=");
+ std::stringstream err;
- size_t signalPos = dataStr.find("Signal= ");
+ size_t signalPos = dataStr.find(signalStr);
if (signalPos == std::string::npos)
{
- //XXX Uh...
+ err << "Couldn't find " << signalStr << " in DTMF INFO body";
+ throw DTMFInfoException(err.str());
+ }
+
+ //The pending draft for DTMF via INFO mandates a single space after
+ //'Signal=' but pre-existing implementations do not necessarily have
+ //any spaces and may do something silly like have multiple spaces.
+ size_t signalValuePos = dataStr.find_first_not_of(' ', signalPos + signalStr.size());
+ char retSignal = dataStr.at(signalValuePos);
+
+ std::string validDTMF("1234567890#*ABCD");
+ if (!validDTMF.find(retSignal))
+ {
+ err << "Signal '" << retSignal << "' is not a valid DTMF signal";
+ throw DTMFInfoException(err.str());
}
- return dataStr.at(signalPos + sizeof("Signal= "));
+ return dataStr.at(signalValuePos);
}
int PJSipSessionModule::getDTMFInfoDuration(pjsip_msg_body *body)
{
char *data = static_cast<char *>(body->data);
std::string dataStr(data, body->len);
+ std::string durationStr("Duration=");
+ std::stringstream err;
- size_t durationPos = dataStr.find("Duration= ");
+ size_t durationPos = dataStr.find(durationStr);
if (durationPos == std::string::npos)
{
- //XXX Uh...
+ err << "Couldn't find " << durationStr << " in DTMF INFO body";
+ throw DTMFInfoException(err.str());
}
- std::string duration(dataStr.substr(durationPos + sizeof("Duration= ")));
- return boost::lexical_cast<int>(duration);
+ //The pending draft for DTMF via INFO mandates a single space after
+ //'Duration=' but pre-existing implementations do not necessarily have
+ //any spaces and may do something silly like have multiple spaces.
+ size_t durationValuePos = durationPos + durationStr.size();
+ size_t durationBegin = dataStr.find_first_not_of(' ', durationValuePos);
+ size_t durationEnd = dataStr.find_first_not_of(" 1234567890", durationValuePos);
+ size_t durationSize = durationEnd - durationBegin;
+ std::string duration(dataStr.substr(durationBegin, durationSize));
+
+ int retDuration;
+ try
+ {
+ retDuration = boost::lexical_cast<int>(duration);
+ }
+ catch (const boost::bad_lexical_cast& ex)
+ {
+ throw DTMFInfoException(ex.what());
+ }
+
+ return retDuration;
}
void PJSipSessionModule::handleInfo(pjsip_inv_session *inv, pjsip_rx_data *rdata)
@@ -986,10 +1070,25 @@ void PJSipSessionModule::handleInfo(pjsip_inv_session *inv, pjsip_rx_data *rdata
return;
}
+ char dtmf;
+ int duration;
//It's DTMF! Grab the info we need! HA THAT WAS A PUN YOU JERK!
- char dtmf = getDTMFInfoSignal(rdata->msg_info.msg->body);
- int duration = getDTMFInfoDuration(rdata->msg_info.msg->body);
+ try
+ {
+ dtmf = getDTMFInfoSignal(rdata->msg_info.msg->body);
+ duration = getDTMFInfoDuration(rdata->msg_info.msg->body);
+ }
+ catch (const DTMFInfoException& ex)
+ {
+ lg(Error) << "Error processing DTMF INFO: " << ex.what();
+ pjsip_dlg_respond(inv->dlg, rdata, 400, NULL, NULL, NULL);
+ return;
+ }
+ pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata);
+ pjsip_tx_data *tdata;
+ pjsip_dlg_create_response(inv->dlg, rdata, 200, NULL, &tdata);
+ enqueueSessionWork(new HandleInfoDTMFOperation(inv, tsx, tdata, dtmf, duration), inv);
return;
}
-----------------------------------------------------------------------
--
asterisk-scf/integration/sip.git
More information about the asterisk-scf-commits
mailing list