Implemented configurable method to send DTMFs: using the protocol, inband, rfc2833 or chat message.

git-svn-id: http://voip.null.ro/svn/yate@4003 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
marian 2010-12-22 08:47:45 +00:00
parent 84129ca775
commit c850455ea0
2 changed files with 68 additions and 9 deletions

View File

@ -105,6 +105,15 @@
; This parameter can be overridden from routing ; This parameter can be overridden from routing
;redirectcount=0 ;redirectcount=0
; dtmfmethod: string: Default value for the method used to send DTMFs
; Allowed values:
; jingle: Use the jingle protocol
; rfc2833: Send RFC 2833 DTMFs
; inband: Generate inband tones
; chat: Send tones as chat messages
; This parameter can be overridden from routing
;dtmfmethod=jingle
[codecs] [codecs]
; This section allows to individually enable or disable the codecs ; This section allows to individually enable or disable the codecs

View File

@ -306,6 +306,8 @@ private:
bool m_offerRawTransport; // Offer RAW transport on outgoing session bool m_offerRawTransport; // Offer RAW transport on outgoing session
bool m_offerIceTransport; // Offer ICE transport on outgoing session bool m_offerIceTransport; // Offer ICE transport on outgoing session
unsigned int m_redirectCount; // Redirect counter unsigned int m_redirectCount; // Redirect counter
int m_dtmfMeth; // Used DMTF method
String m_rtpId; // Started RTP id
// Crypto (for contents created by us) // Crypto (for contents created by us)
bool m_secure; // The channel is using crypto bool m_secure; // The channel is using crypto
bool m_secureRequired; // Crypto is mandatory bool m_secureRequired; // Crypto is mandatory
@ -381,6 +383,14 @@ private:
class YJGDriver : public Driver class YJGDriver : public Driver
{ {
public: public:
// Dtmf type
enum DtmfType {
DtmfUnknown = 0,
DtmfRfc2833, // Send RFC 2833 tones
DtmfInband, // Send inband tones
DtmfJingle, // Use the jingle protocol
DtmfChat // Send chat
};
YJGDriver(); YJGDriver();
virtual ~YJGDriver(); virtual ~YJGDriver();
// Check if a message was sent by us // Check if a message was sent by us
@ -510,6 +520,7 @@ static bool s_offerRawTransport = true; // Offer RAW UDP transport on
static bool s_offerIceTransport = true; // Offer ICE UDP transport on outgoing sessions static bool s_offerIceTransport = true; // Offer ICE UDP transport on outgoing sessions
static int s_priority = 0; // Resource priority for presence generated by this module static int s_priority = 0; // Resource priority for presence generated by this module
static unsigned int s_redirectCount = 0; // Redirect counter static unsigned int s_redirectCount = 0; // Redirect counter
static int s_dtmfMeth; // Default DTMF method to use
static JGSession::Version s_sessVersion = JGSession::VersionUnknown; // Default jingle session version for outgoing calls static JGSession::Version s_sessVersion = JGSession::VersionUnknown; // Default jingle session version for outgoing calls
static String s_capsNode = "http://yate.null.ro/yate/jingle/caps"; // node for entity capabilities static String s_capsNode = "http://yate.null.ro/yate/jingle/caps"; // node for entity capabilities
static bool s_serverMode = true; // Server/client mode static bool s_serverMode = true; // Server/client mode
@ -569,6 +580,15 @@ static TokenDict s_errMap[] = {
{0,0} {0,0}
}; };
// Error mapping
static const TokenDict s_dictDtmfMeth[] = {
{"rfc2833", YJGDriver::DtmfRfc2833},
{"inband", YJGDriver::DtmfInband},
{"jingle", YJGDriver::DtmfJingle},
{"chat", YJGDriver::DtmfChat},
{0,0}
};
static inline void addValidParam(Message& m, const char* param, const char* value) static inline void addValidParam(Message& m, const char* param, const char* value)
{ {
@ -721,7 +741,7 @@ YJGConnection::YJGConnection(Message& msg, const char* caller, const char* calle
m_callerPrompt(msg.getValue("callerprompt")), m_callerPrompt(msg.getValue("callerprompt")),
m_localip(localip), m_localip(localip),
m_offerRawTransport(true), m_offerIceTransport(true), m_offerRawTransport(true), m_offerIceTransport(true),
m_redirectCount(s_redirectCount), m_redirectCount(s_redirectCount), m_dtmfMeth(s_dtmfMeth),
m_secure(s_useCrypto), m_secureRequired(s_cryptoMandatory), m_secure(s_useCrypto), m_secureRequired(s_cryptoMandatory),
m_hangup(false), m_timeout(0), m_transferring(false), m_recvTransferStanza(0), m_hangup(false), m_timeout(0), m_transferring(false), m_recvTransferStanza(0),
m_dataFlags(0), m_ftStatus(FTNone), m_ftHostDirection(FTHostNone), m_dataFlags(0), m_ftStatus(FTNone), m_ftHostDirection(FTHostNone),
@ -729,6 +749,7 @@ YJGConnection::YJGConnection(Message& msg, const char* caller, const char* calle
{ {
int redir = msg.getIntValue("redirectcount",m_redirectCount); int redir = msg.getIntValue("redirectcount",m_redirectCount);
m_redirectCount = (redir >= 0) ? redir : 0; m_redirectCount = (redir >= 0) ? redir : 0;
m_dtmfMeth = msg.getIntValue("dtmfmethod",s_dictDtmfMeth,s_dtmfMeth);
m_secure = msg.getBoolValue("secure",m_secure); m_secure = msg.getBoolValue("secure",m_secure);
m_secureRequired = msg.getBoolValue("secure_required",m_secureRequired); m_secureRequired = msg.getBoolValue("secure_required",m_secureRequired);
overrideJingleVersion(msg,false); overrideJingleVersion(msg,false);
@ -814,7 +835,8 @@ YJGConnection::YJGConnection(JGEvent* event)
m_sessVersion(event->session()->version()), m_sessVersion(event->session()->version()),
m_local(event->session()->local()), m_remote(event->session()->remote()), m_local(event->session()->local()), m_remote(event->session()->remote()),
m_audioContent(0), m_audioContent(0),
m_offerRawTransport(true), m_offerIceTransport(true), m_redirectCount(0), m_offerRawTransport(true), m_offerIceTransport(true),
m_redirectCount(0), m_dtmfMeth(s_dtmfMeth),
m_secure(s_useCrypto), m_secureRequired(s_cryptoMandatory), m_secure(s_useCrypto), m_secureRequired(s_cryptoMandatory),
m_hangup(false), m_timeout(0), m_transferring(false), m_recvTransferStanza(0), m_hangup(false), m_timeout(0), m_transferring(false), m_recvTransferStanza(0),
m_dataFlags(0), m_ftStatus(FTNone), m_ftHostDirection(FTHostNone), m_dataFlags(0), m_ftStatus(FTNone), m_ftHostDirection(FTHostNone),
@ -1043,8 +1065,11 @@ bool YJGConnection::msgAnswered(Message& msg)
{ {
Debug(this,DebugCall,"msgAnswered [%p]",this); Debug(this,DebugCall,"msgAnswered [%p]",this);
if (m_ftStatus == FTNone) { if (m_ftStatus == FTNone) {
if (m_sessVersion != JGSession::Version0) if (m_sessVersion != JGSession::Version0) {
clearEndpoint(); clearEndpoint();
Lock lock(m_mutex);
m_rtpId.clear();
}
m_mutex.lock(); m_mutex.lock();
if (m_sessVersion != JGSession::Version0 || !m_rtpStarted) if (m_sessVersion != JGSession::Version0 || !m_rtpStarted)
resetCurrentAudioContent(true,false,true); resetCurrentAudioContent(true,false,true);
@ -1213,18 +1238,35 @@ bool YJGConnection::msgTone(Message& msg, const char* tone)
DDebug(this,DebugCall,"msgTone. '%s' [%p]",tone,this); DDebug(this,DebugCall,"msgTone. '%s' [%p]",tone,this);
if (!(tone && *tone)) if (!(tone && *tone))
return true; return true;
int meth = msg.getIntValue("method",s_dictDtmfMeth,m_dtmfMeth);
Lock lock(m_mutex); Lock lock(m_mutex);
// Inband and RFC 2833 require an active local RTP stream
if (meth == YJGDriver::DtmfInband) {
if (m_rtpId && dtmfInband(tone))
return true;
}
else if (meth == YJGDriver::DtmfRfc2833) {
if (m_rtpId) {
msg.setParam("targetid",m_rtpId);
return false;
}
}
if (!m_session) if (!m_session)
return true; return false;
if (s_singleTone) { if (s_singleTone) {
char s[2] = {0,0}; char s[2] = {0,0};
while (*tone) { while (*tone) {
s[0] = *tone++; s[0] = *tone++;
m_session->sendDtmf(s); if (meth != YJGDriver::DtmfChat)
m_session->sendDtmf(s);
else
s_jingle->sendMessage(m_session,s);
} }
} }
else else if (meth != YJGDriver::DtmfChat)
m_session->sendDtmf(tone); m_session->sendDtmf(tone);
else
s_jingle->sendMessage(m_session,tone);
return true; return true;
} }
@ -1991,6 +2033,7 @@ bool YJGConnection::updateCandidate(unsigned int component, JGSessionContent& lo
rtp = 0; rtp = 0;
clearEndpoint(); clearEndpoint();
m_rtpStarted = false; m_rtpStarted = false;
m_rtpId.clear();
} }
} }
// Any other transport type accepted only initially // Any other transport type accepted only initially
@ -2064,8 +2107,10 @@ void YJGConnection::removeContent(JGSessionContent* c)
// add a new identical content and remove the old old one from the session // add a new identical content and remove the old old one from the session
void YJGConnection::removeCurrentAudioContent(bool removeReq) void YJGConnection::removeCurrentAudioContent(bool removeReq)
{ {
if (!dataFlags(OnHold)) if (!dataFlags(OnHold)) {
clearEndpoint(); clearEndpoint();
m_rtpId.clear();
}
if (!m_audioContent) if (!m_audioContent)
return; return;
@ -2206,6 +2251,7 @@ bool YJGConnection::startRtp()
return false; return false;
} }
m_rtpId = m.getValue("rtpid");
rtpLocal->m_port = m.getValue("localport"); rtpLocal->m_port = m.getValue("localport");
Debug(this,DebugAll, Debug(this,DebugAll,
@ -2232,7 +2278,7 @@ bool YJGConnection::startRtp()
m_audioContent->m_rtpRemoteCandidates.m_ufrag); m_audioContent->m_rtpRemoteCandidates.m_ufrag);
msg->addParam("remoteip",rtpRemote->m_address.c_str()); msg->addParam("remoteip",rtpRemote->m_address.c_str());
msg->addParam("remoteport",rtpRemote->m_port); msg->addParam("remoteport",rtpRemote->m_port);
msg->addParam("userid",m.getValue("rtpid")); msg->addParam("userid",m_rtpId);
Engine::enqueue(msg); Engine::enqueue(msg);
} }
else if (m_audioContent->m_rtpLocalCandidates.m_type == JGRtpCandidates::RtpRawUdp) { else if (m_audioContent->m_rtpLocalCandidates.m_type == JGRtpCandidates::RtpRawUdp) {
@ -2923,8 +2969,10 @@ void YJGConnection::handleAudioInfoEvent(JGEvent* event)
m->setParam(what->tag(),String::boolText(true)); m->setParam(what->tag(),String::boolText(true));
// Clear endpoint before dispatching the message // Clear endpoint before dispatching the message
// Our data source/consumer may be replaced // Our data source/consumer may be replaced
if (hold) if (hold) {
clearEndpoint(); clearEndpoint();
m_rtpId.clear();
}
Engine::dispatch(*m); Engine::dispatch(*m);
TelEngine::destruct(m); TelEngine::destruct(m);
// Reset data transport when put on hold // Reset data transport when put on hold
@ -2998,6 +3046,7 @@ void YJGConnection::copySessionParams(NamedList& list, bool redirect)
jingleAddParam(list,"secure_required",String::boolText(m_secureRequired),copy); jingleAddParam(list,"secure_required",String::boolText(m_secureRequired),copy);
jingleAddParam(list,"offerrawudp",String::boolText(m_offerRawTransport),copy); jingleAddParam(list,"offerrawudp",String::boolText(m_offerRawTransport),copy);
jingleAddParam(list,"offericeudp",String::boolText(m_offerIceTransport),copy); jingleAddParam(list,"offericeudp",String::boolText(m_offerIceTransport),copy);
jingleAddParam(list,"dtmfmethod",lookup(m_dtmfMeth,s_dictDtmfMeth),copy,false);
// File transfer // File transfer
JGSessionContent* c = firstFTContent(); JGSessionContent* c = firstFTContent();
if (!c) if (!c)
@ -3300,6 +3349,7 @@ void YJGDriver::initialize()
s_offerIceTransport = sect->getBoolValue("offericeudp",true); s_offerIceTransport = sect->getBoolValue("offericeudp",true);
int redir = sect->getIntValue("redirectcount"); int redir = sect->getIntValue("redirectcount");
s_redirectCount = (redir >= 0) ? redir : 0; s_redirectCount = (redir >= 0) ? redir : 0;
s_dtmfMeth = sect->getIntValue("dtmfmethod",s_dictDtmfMeth,DtmfJingle);
int prio = sect->getIntValue("resource_priority"); int prio = sect->getIntValue("resource_priority");
if (prio < -128) if (prio < -128)