Honor detected method when sending DTMFs.
git-svn-id: http://yate.null.ro/svn/yate/trunk@5277 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
08654d5b53
commit
ec97de2487
|
@ -49,6 +49,15 @@
|
|||
; This parameter is applied on reload for new calls only
|
||||
;dtmfmethods=rfc2833,h323,inband
|
||||
|
||||
; honor_dtmf_detect: bool: Honor DTMF detected method when sending DTMFs
|
||||
; If enabled the channel will try to send a DTMF using the same method as received
|
||||
; If the detected method is not enabled it won't be used
|
||||
; This parameter can be overridden from routing by 'ohonor_dtmf_detect' for outgoing call leg
|
||||
; and 'ihonor_dtmf_detect' for incoming call leg
|
||||
; This parameter is applied on reload for new calls only
|
||||
; Defaults to enable
|
||||
;honor_dtmf_detect=enable
|
||||
|
||||
; Use an external RTP module instead of the native OpenH323 RTP stack, which is
|
||||
; very cpu intensive. If no external RTP can be found it will fallback to the
|
||||
; native stack. The only external RTP now is yrtp (see the yrtpchan module).
|
||||
|
|
|
@ -130,6 +130,15 @@
|
|||
; This parameter is applied on reload for new calls only
|
||||
;dtmfmethods=rfc2833,info,inband
|
||||
|
||||
; honor_dtmf_detect: bool: Honor DTMF detected method when sending DTMFs
|
||||
; If enabled the channel will try to send a DTMF using the same method as received
|
||||
; If the detected method is not enabled it won't be used
|
||||
; This parameter can be overridden from routing by 'ohonor_dtmf_detect' for outgoing call leg
|
||||
; and 'ihonor_dtmf_detect' for incoming call leg
|
||||
; This parameter is applied on reload for new calls only
|
||||
; Defaults to enable
|
||||
;honor_dtmf_detect=enable
|
||||
|
||||
; rfc2833: bool: Offer RFC2833 telephone-event by default
|
||||
; A numeric payload >= 96 can be provided
|
||||
;rfc2833=yes
|
||||
|
|
|
@ -525,7 +525,6 @@ public:
|
|||
void stoppedExternal(H323Channel::Directions dir);
|
||||
void setRemoteAddress(const char* remoteIP, WORD remotePort);
|
||||
void cleanups(bool closeChans = true, bool dropChan = true);
|
||||
bool sendTone(Message& msg, const char* tone);
|
||||
void setCallerID(const char* number, const char* name);
|
||||
void rtpExecuted(Message& msg);
|
||||
void rtpForward(Message& msg, bool init = false);
|
||||
|
@ -622,10 +621,14 @@ public:
|
|||
protected:
|
||||
virtual void endDisconnect(const Message& msg, bool handled);
|
||||
private:
|
||||
// Send tone(s) using method
|
||||
bool sendTone(Message& msg, const char* tone, int meth, bool& retVal);
|
||||
|
||||
YateH323Connection* m_conn;
|
||||
H323Connection::CallEndReason m_reason;
|
||||
bool m_hungup;
|
||||
DtmfMethods m_dtmfMethods;
|
||||
bool m_honorDtmfDetect;
|
||||
};
|
||||
|
||||
class YateGkRegThread : public PThread
|
||||
|
@ -759,6 +762,7 @@ protected:
|
|||
unsigned int YateGkRegThread::s_count = 0;
|
||||
Mutex YateGkRegThread::s_mutexCount(false,"H323GkThreads");
|
||||
static DtmfMethods s_dtmfMethods;
|
||||
static bool s_honorDtmfDetect = true;
|
||||
// Deprecated dtmf params warn
|
||||
static bool s_warnDtmfInbandCfg = true;
|
||||
static bool s_warnDtmfInbandCallExecute = true;
|
||||
|
@ -2382,17 +2386,6 @@ void YateH323Connection::stoppedExternal(H323Channel::Directions dir)
|
|||
}
|
||||
}
|
||||
|
||||
bool YateH323Connection::sendTone(Message& msg, const char* tone)
|
||||
{
|
||||
if (m_rtpid) {
|
||||
msg.setParam("targetid",m_rtpid);
|
||||
return false;
|
||||
}
|
||||
while (*tone)
|
||||
SendUserInputTone(*tone++);
|
||||
return true;
|
||||
}
|
||||
|
||||
void YateH323Connection::setEpConn(bool created)
|
||||
{
|
||||
YateH323EndPoint* ep = static_cast<YateH323EndPoint*>(&endpoint);
|
||||
|
@ -2784,7 +2777,8 @@ void YateH323Connection::setCallerID(const char* number, const char* name)
|
|||
YateH323Chan::YateH323Chan(YateH323Connection* conn,Message* msg,const char* addr)
|
||||
: Channel(hplugin,0,(msg != 0)),
|
||||
m_conn(conn), m_reason(H323Connection::EndedByLocalUser),
|
||||
m_hungup(false)
|
||||
m_hungup(false),
|
||||
m_honorDtmfDetect(s_honorDtmfDetect)
|
||||
{
|
||||
s_mutex.lock();
|
||||
s_chanCount++;
|
||||
|
@ -2806,6 +2800,7 @@ YateH323Chan::YateH323Chan(YateH323Connection* conn,Message* msg,const char* add
|
|||
else
|
||||
m_dtmfMethods.getDeprecatedDtmfMethod(*msg,"dtmfinband",DtmfMethods::Inband,&s_warnDtmfInbandCallExecute);
|
||||
s->copyParams(*msg,"caller,callername,called,billid,callto,username");
|
||||
m_honorDtmfDetect = msg->getBoolValue(YSTRING("ohonor_dtmf_detect"),m_honorDtmfDetect);
|
||||
}
|
||||
Engine::enqueue(s);
|
||||
}
|
||||
|
@ -2915,6 +2910,33 @@ void YateH323Chan::endDisconnect(const Message& msg, bool handled)
|
|||
#endif
|
||||
}
|
||||
|
||||
// Send tone(s) using method
|
||||
bool YateH323Chan::sendTone(Message& msg, const char* tone, int meth, bool& retVal)
|
||||
{
|
||||
if (!(m_conn && tone))
|
||||
return false;
|
||||
bool ok = false;
|
||||
if (meth == DtmfMethods::H323) {
|
||||
const char* t = tone;
|
||||
while (*t)
|
||||
m_conn->SendUserInputTone(*t++);
|
||||
retVal = true;
|
||||
ok = true;
|
||||
}
|
||||
else if (meth == DtmfMethods::Rfc2833) {
|
||||
ok = m_conn->rtpStarted() && m_conn->rtpId() && m_conn->dtmfPayload() > 0;
|
||||
if (ok)
|
||||
msg.setParam("targetid",m_conn->rtpId());
|
||||
}
|
||||
else if (meth == DtmfMethods::Inband) {
|
||||
ok = dtmfInband(tone);
|
||||
retVal = ok;
|
||||
}
|
||||
XDebug(this,ok ? DebugAll : DebugNote,"sendTone(%s) meth=%s (%d) ok=%u [%p]",
|
||||
tone,lookup(meth,DtmfMethods::s_methodName),meth,ok,this);
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Set the signalling address
|
||||
void YateH323Chan::setAddress(const char* addr)
|
||||
{
|
||||
|
@ -2994,6 +3016,7 @@ void YateH323Chan::callAccept(Message& msg)
|
|||
DtmfMethods old = m_dtmfMethods;
|
||||
m_dtmfMethods.set(*meths,&old);
|
||||
}
|
||||
m_honorDtmfDetect = msg.getBoolValue(YSTRING("ihonor_dtmf_detect"),m_honorDtmfDetect);
|
||||
Channel::callAccept(msg);
|
||||
if (m_conn) {
|
||||
m_conn->rtpExecuted(msg);
|
||||
|
@ -3056,23 +3079,18 @@ bool YateH323Chan::msgTone(Message& msg, const char* tone)
|
|||
}
|
||||
bool retVal = false;
|
||||
bool ok = false;
|
||||
if (msg.getBoolValue(YSTRING("honor_dtmf_detect"),m_honorDtmfDetect)) {
|
||||
const String& detected = msg[YSTRING("detected")];
|
||||
int meth = lookup(detected,DtmfMethods::s_methodName,DtmfMethods::MethodCount);
|
||||
if (meth != DtmfMethods::MethodCount && methods.hasMethod(meth)) {
|
||||
ok = sendTone(msg,tone,meth,retVal);
|
||||
methods.reset(meth);
|
||||
}
|
||||
}
|
||||
for (int i = 0; !ok && i < DtmfMethods::MethodCount; i++) {
|
||||
int meth = methods[i];
|
||||
if (meth == DtmfMethods::H323) {
|
||||
while (*tone)
|
||||
m_conn->SendUserInputTone(*tone++);
|
||||
ok = true;
|
||||
retVal = true;
|
||||
}
|
||||
else if (meth == DtmfMethods::Rfc2833) {
|
||||
ok = m_conn->rtpStarted() && m_conn->rtpId() && m_conn->dtmfPayload() > 0;
|
||||
if (ok)
|
||||
msg.setParam("targetid",m_conn->rtpId());
|
||||
}
|
||||
else if (meth == DtmfMethods::Inband) {
|
||||
ok = dtmfInband(tone);
|
||||
retVal = ok;
|
||||
}
|
||||
if (meth != DtmfMethods::MethodCount)
|
||||
ok = sendTone(msg,tone,meth,retVal);
|
||||
}
|
||||
if (!ok && debugAt(DebugNote)) {
|
||||
String tmp;
|
||||
|
@ -3280,6 +3298,7 @@ void H323Driver::initialize()
|
|||
else
|
||||
s_dtmfMethods.setDefault();
|
||||
s_cfgMutex.unlock();
|
||||
s_honorDtmfDetect = s_cfg.getBoolValue("general","honor_dtmf_detect",true);
|
||||
s_externalRtp = s_cfg.getBoolValue("general","external_rtp",true);
|
||||
s_passtrough = s_cfg.getBoolValue("general","forward_rtp",false);
|
||||
s_fallbackRtp = s_cfg.getBoolValue("general","fallback_rtp",true);
|
||||
|
|
|
@ -940,6 +940,8 @@ private:
|
|||
void updateRtpNatAddress(NamedList* params = 0);
|
||||
// Process allow list. Get INFO support
|
||||
bool infoAllowed(const SIPMessage* msg);
|
||||
// Send tone(s) using method
|
||||
bool sendTone(Message& msg, const char* tone, int meth, bool& retVal);
|
||||
|
||||
SIPTransaction* m_tr;
|
||||
SIPTransaction* m_tr2;
|
||||
|
@ -967,6 +969,7 @@ private:
|
|||
bool m_checkAllowInfo; // Check Allow in INVITE and OK for INFO support
|
||||
bool m_missingAllowInfoDefVal; // Default INFO support if Allow header is missing
|
||||
DtmfMethods m_dtmfMethods;
|
||||
bool m_honorDtmfDetect;
|
||||
// REFER already running
|
||||
bool m_referring;
|
||||
// reINVITE requested or in progress
|
||||
|
@ -1132,6 +1135,7 @@ int YateSIPEndPoint::s_evCount = 0;
|
|||
static bool s_checkAllowInfo = true; // Check Allow in INVITE and OK for INFO support
|
||||
static bool s_missingAllowInfoDefVal = true; // Default INFO support if Allow header is missing
|
||||
static DtmfMethods s_dtmfMethods;
|
||||
static bool s_honorDtmfDetect = true;
|
||||
// Deprecated dtmf params warn
|
||||
static bool s_warnDtmfInfoCfg = true;
|
||||
static bool s_warnDtmfInbandCfg = true;
|
||||
|
@ -1143,6 +1147,7 @@ const TokenDict DtmfMethods::s_methodName[] = {
|
|||
{ "info", Info},
|
||||
{ "rfc2833", Rfc2833},
|
||||
{ "inband", Inband},
|
||||
{ "sip-info", Info},
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
|
@ -5075,6 +5080,7 @@ YateSIPConnection::YateSIPConnection(SIPEvent* ev, SIPTransaction* tr)
|
|||
m_state(Incoming), m_port(0), m_route(0), m_routes(0),
|
||||
m_authBye(true),
|
||||
m_checkAllowInfo(s_checkAllowInfo), m_missingAllowInfoDefVal(s_missingAllowInfoDefVal),
|
||||
m_honorDtmfDetect(s_honorDtmfDetect),
|
||||
m_referring(false), m_reInviting(ReinviteNone), m_lastRseq(0)
|
||||
{
|
||||
Debug(this,DebugAll,"YateSIPConnection::YateSIPConnection(%p,%p) [%p]",ev,tr,this);
|
||||
|
@ -5247,6 +5253,7 @@ YateSIPConnection::YateSIPConnection(Message& msg, const String& uri, const char
|
|||
m_state(Outgoing), m_port(0), m_route(0), m_routes(0),
|
||||
m_authBye(false),
|
||||
m_checkAllowInfo(s_checkAllowInfo), m_missingAllowInfoDefVal(s_missingAllowInfoDefVal),
|
||||
m_honorDtmfDetect(s_honorDtmfDetect),
|
||||
m_referring(false), m_reInviting(ReinviteNone), m_lastRseq(0)
|
||||
{
|
||||
Debug(this,DebugAll,"YateSIPConnection::YateSIPConnection(%p,'%s') [%p]",
|
||||
|
@ -5265,6 +5272,7 @@ YateSIPConnection::YateSIPConnection(Message& msg, const String& uri, const char
|
|||
m_dtmfMethods.getDeprecatedDtmfMethod(msg,"dtmfinband",DtmfMethods::Inband,&s_warnDtmfInbandCallExecute);
|
||||
}
|
||||
s_globalMutex.unlock();
|
||||
m_honorDtmfDetect = msg.getBoolValue(YSTRING("ohonor_dtmf_detect"),m_honorDtmfDetect);
|
||||
m_secure = msg.getBoolValue(YSTRING("secure"),plugin.parser().secure());
|
||||
setRfc2833(msg.getParam(YSTRING("rfc2833")));
|
||||
m_rtpForward = msg.getBoolValue(YSTRING("rtp_forward"));
|
||||
|
@ -6581,60 +6589,25 @@ bool YateSIPConnection::msgTone(Message& msg, const char* tone)
|
|||
s_warnDtmfMethodChanDtmf = false;
|
||||
Debug(this,DebugConf,"Deprecated 'method' parameter in '%s'. Use 'methods' instead!",msg.c_str());
|
||||
}
|
||||
if ((*method == YSTRING("info")) || (*method == YSTRING("sip-info")))
|
||||
methods.set(DtmfMethods::Info);
|
||||
else if (*method == YSTRING("rfc2833"))
|
||||
methods.set(DtmfMethods::Rfc2833);
|
||||
else if (*method == YSTRING("inband"))
|
||||
methods.set(DtmfMethods::Inband);
|
||||
int meth = lookup(*method,DtmfMethods::s_methodName,DtmfMethods::MethodCount);
|
||||
if (meth != DtmfMethods::MethodCount)
|
||||
methods.set(meth);
|
||||
}
|
||||
}
|
||||
bool retVal = false;
|
||||
bool ok = false;
|
||||
if (msg.getBoolValue(YSTRING("honor_dtmf_detect"),m_honorDtmfDetect)) {
|
||||
const String& detected = msg[YSTRING("detected")];
|
||||
int meth = lookup(detected,DtmfMethods::s_methodName,DtmfMethods::MethodCount);
|
||||
if (meth != DtmfMethods::MethodCount && methods.hasMethod(meth)) {
|
||||
ok = sendTone(msg,tone,meth,retVal);
|
||||
methods.reset(meth);
|
||||
}
|
||||
}
|
||||
for (int i = 0; !ok && i < DtmfMethods::MethodCount; i++) {
|
||||
int meth = methods[i];
|
||||
if (meth == DtmfMethods::Info) {
|
||||
// Send INFO only if initial transaction finished
|
||||
if (m_tr)
|
||||
continue;
|
||||
for (; tone && *tone; tone++) {
|
||||
char c = *tone;
|
||||
for (int j = 0; j <= 16; j++) {
|
||||
if (s_dtmfs[j] != c)
|
||||
continue;
|
||||
SIPMessage* m = createDlgMsg("INFO");
|
||||
if (!m)
|
||||
break;
|
||||
copySipHeaders(*m,msg);
|
||||
String tmp;
|
||||
tmp << "Signal=" << j << "\r\n";
|
||||
m->setBody(new MimeStringBody("application/dtmf-relay",tmp));
|
||||
plugin.ep()->engine()->addMessage(m);
|
||||
m->deref();
|
||||
break;
|
||||
}
|
||||
}
|
||||
ok = true;
|
||||
retVal = true;
|
||||
}
|
||||
else if (meth == DtmfMethods::Rfc2833 || meth == DtmfMethods::Inband) {
|
||||
// RFC2833 and inband require media to be started
|
||||
if (!(m_rtpMedia && (m_mediaStatus == MediaStarted)))
|
||||
continue;
|
||||
ObjList* l = m_rtpMedia->find("audio");
|
||||
const SDPMedia* m = static_cast<const SDPMedia*>(l ? l->get() : 0);
|
||||
if (!m)
|
||||
continue;
|
||||
if (meth == DtmfMethods::Rfc2833) {
|
||||
ok = m->rfc2833().toBoolean(true);
|
||||
if (ok)
|
||||
msg.setParam("targetid",m->id());
|
||||
}
|
||||
else {
|
||||
ok = dtmfInband(tone);
|
||||
retVal = ok;
|
||||
}
|
||||
}
|
||||
if (meth != DtmfMethods::MethodCount)
|
||||
ok = sendTone(msg,tone,meth,retVal);
|
||||
}
|
||||
if (!ok && debugAt(DebugNote)) {
|
||||
String tmp;
|
||||
|
@ -6877,6 +6850,7 @@ void YateSIPConnection::callAccept(Message& msg)
|
|||
// Update dtmf methods from message
|
||||
m_checkAllowInfo = msg.getBoolValue(YSTRING("icheck_allow_info"),m_checkAllowInfo);
|
||||
m_missingAllowInfoDefVal = msg.getBoolValue(YSTRING("imissing_allow_info"),m_missingAllowInfoDefVal);
|
||||
m_honorDtmfDetect = msg.getBoolValue(YSTRING("ihonor_dtmf_detect"),m_honorDtmfDetect);
|
||||
String* meths = msg.getParam(YSTRING("idtmfmethods"));
|
||||
if (meths) {
|
||||
DtmfMethods old = m_dtmfMethods;
|
||||
|
@ -7144,6 +7118,56 @@ bool YateSIPConnection::infoAllowed(const SIPMessage* msg)
|
|||
return ok;
|
||||
}
|
||||
|
||||
// Send tone(s) using method
|
||||
bool YateSIPConnection::sendTone(Message& msg, const char* tone, int meth, bool& retVal)
|
||||
{
|
||||
bool ok = false;
|
||||
if (meth == DtmfMethods::Info) {
|
||||
// Send INFO only if initial transaction finished
|
||||
if (!m_tr) {
|
||||
const char* t = tone;
|
||||
for (; t && *t; t++) {
|
||||
char c = *t;
|
||||
for (int j = 0; j <= 16; j++) {
|
||||
if (s_dtmfs[j] != c)
|
||||
continue;
|
||||
SIPMessage* m = createDlgMsg("INFO");
|
||||
if (!m)
|
||||
break;
|
||||
copySipHeaders(*m,msg);
|
||||
String tmp;
|
||||
tmp << "Signal=" << j << "\r\n";
|
||||
m->setBody(new MimeStringBody("application/dtmf-relay",tmp));
|
||||
plugin.ep()->engine()->addMessage(m);
|
||||
m->deref();
|
||||
break;
|
||||
}
|
||||
}
|
||||
retVal = true;
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
else if (meth == DtmfMethods::Rfc2833 || meth == DtmfMethods::Inband) {
|
||||
// RFC2833 and inband require media to be started
|
||||
if (m_rtpMedia && (m_mediaStatus == MediaStarted)) {
|
||||
ObjList* l = m_rtpMedia->find("audio");
|
||||
const SDPMedia* m = static_cast<const SDPMedia*>(l ? l->get() : 0);
|
||||
if (meth == DtmfMethods::Rfc2833) {
|
||||
ok = m && m->rfc2833().toBoolean(true);
|
||||
if (ok)
|
||||
msg.setParam("targetid",m->id());
|
||||
}
|
||||
else if (m) {
|
||||
ok = dtmfInband(tone);
|
||||
retVal = ok;
|
||||
}
|
||||
}
|
||||
}
|
||||
XDebug(this,ok ? DebugAll : DebugNote,"sendTone(%s) meth=%s (%d) ok=%u [%p]",
|
||||
tone,lookup(meth,DtmfMethods::s_methodName),meth,ok,this);
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
YateSIPLine::YateSIPLine(const String& name)
|
||||
: String(name), Mutex(true,"YateSIPLine"),
|
||||
|
@ -7983,6 +8007,7 @@ void SIPDriver::initialize()
|
|||
s_globalMutex.unlock();
|
||||
s_checkAllowInfo = s_cfg.getBoolValue("general","check_allow_info",true);
|
||||
s_missingAllowInfoDefVal = s_cfg.getBoolValue("general","missing_allow_info",true);
|
||||
s_honorDtmfDetect = s_cfg.getBoolValue("general","honor_dtmf_detect",true);
|
||||
s_maxForwards = s_cfg.getIntValue("general","maxforwards",20);
|
||||
s_floodEvents = s_cfg.getIntValue("general","floodevents",100);
|
||||
s_floodProtection = s_cfg.getBoolValue("general","floodprotection",true);
|
||||
|
|
Loading…
Reference in New Issue