diff --git a/conf.d/mgcpca.conf.sample b/conf.d/mgcpca.conf.sample index 7a48eb1b..ba4a014f 100644 --- a/conf.d/mgcpca.conf.sample +++ b/conf.d/mgcpca.conf.sample @@ -4,6 +4,10 @@ ; priority: int: Priority of the chan.rtp message handler ;priority=80 +; rfc2833: bool: Offer RFC2833 telephone-event by default +; A numeric payload >= 96 can be provided +;rfc2833=yes + ; tzoffset: int: Timezone offset from GMT in seconds for sending Caller ID ; Positive to go East, negative to go West ; Examples: CET=3600, EST=-18000 diff --git a/conf.d/ysipchan.conf.sample b/conf.d/ysipchan.conf.sample index 66f95d59..529c1989 100644 --- a/conf.d/ysipchan.conf.sample +++ b/conf.d/ysipchan.conf.sample @@ -73,6 +73,7 @@ ;dtmfinfo=no ; rfc2833: bool: Offer RFC2833 telephone-event by default +; A numeric payload >= 96 can be provided ;rfc2833=yes ; privacy: bool: Process and generate privacy related SIP headers diff --git a/libs/ysdp/parser.cpp b/libs/ysdp/parser.cpp index fd3e871d..80159889 100644 --- a/libs/ysdp/parser.cpp +++ b/libs/ysdp/parser.cpp @@ -325,11 +325,17 @@ void SDPParser::initialize(const NamedList* codecs, const NamedList* hacks, cons } DDebug(this,DebugNote,"Default audio codecs: %s",m_audioFormats.c_str()); m_ignorePort = m_hacks.getBoolValue("ignore_sdp_port",false); - m_rfc2833 = true; + m_rfc2833 = 101; m_secure = false; m_sdpForward = false; if (general) { - m_rfc2833 = general->getBoolValue("rfc2833",m_rfc2833); + if (general->getBoolValue("rfc2833",true)) { + m_rfc2833 = general->getIntValue("rfc2833",m_rfc2833); + if (m_rfc2833 < 96 || m_rfc2833 > 127) + m_rfc2833 = 101; + } + else + m_rfc2833 = -1; m_secure = general->getBoolValue("secure",m_secure); m_sdpForward = general->getBoolValue("forward_sdp",m_sdpForward); } diff --git a/libs/ysdp/session.cpp b/libs/ysdp/session.cpp index ca5f7968..d32d13e8 100644 --- a/libs/ysdp/session.cpp +++ b/libs/ysdp/session.cpp @@ -44,7 +44,8 @@ SDPSession::SDPSession(SDPParser* parser, NamedList& params) { m_rtpForward = params.getBoolValue("rtp_forward"); m_secure = params.getBoolValue("secure",parser->m_secure); - m_rfc2833 = params.getBoolValue("rfc2833",parser->m_rfc2833); + m_rfc2833 = parser->m_rfc2833; + setRfc2833(params.getParam("rfc2833")); } SDPSession::~SDPSession() @@ -94,6 +95,18 @@ void SDPSession::putMedia(NamedList& msg, ObjList* mList, bool putPort) msg.setParam("media",String::boolText(false)); } +// Update the RFC 2833 availability and payload +void SDPSession::setRfc2833(const String& value) +{ + if (value.toBoolean(true)) { + m_rfc2833 = value.toInteger(m_parser->m_rfc2833); + if (m_rfc2833 < 96 || m_rfc2833 > 127) + m_rfc2833 = value.toBoolean(false) ? 101 : m_parser->m_rfc2833; + } + else + m_rfc2833 = -1; +} + // Build and dispatch a chan.rtp message for a given media. Update media on success bool SDPSession::dispatchRtp(SDPMedia* media, const char* addr, bool start, bool pick, RefObject* context) @@ -382,9 +395,9 @@ MimeSdpBody* SDPSession::createSDP(const char* addr, ObjList* mediaList) TelEngine::destruct(l); TelEngine::destruct(map); - if (m_rfc2833 && frm && m->isAudio()) { - int rfc2833 = m->rfc2833().toInteger(-1); - if (rfc2833 < 0) + if ((m_rfc2833 >= 0) && frm && m->isAudio()) { + int rfc2833 = m->rfc2833().toInteger(m_rfc2833); + if (rfc2833 < 96 || rfc2833 > 127) rfc2833 = 101; // claim to support telephone events frm << " " << rfc2833; @@ -610,7 +623,7 @@ bool SDPSession::addRtpParams(NamedList& msg, const String& natAddr, } // Reset this object to default values -void SDPSession::resetSdp() +void SDPSession::resetSdp(bool all) { m_mediaStatus = MediaMissing; TelEngine::destruct(m_rtpMedia); @@ -622,8 +635,10 @@ void SDPSession::resetSdp() m_sdpSession = 0; m_sdpVersion = 0; m_host.clear(); - m_secure = m_parser->secure(); - m_rfc2833 = m_parser->rfc2833(); + if (all) { + m_secure = m_parser->secure(); + m_rfc2833 = m_parser->rfc2833(); + } } // Build a populated chan.rtp message diff --git a/libs/ysdp/yatesdp.h b/libs/ysdp/yatesdp.h index 5e84682e..eff5a9f8 100644 --- a/libs/ysdp/yatesdp.h +++ b/libs/ysdp/yatesdp.h @@ -387,6 +387,27 @@ public: inline void putMedia(NamedList& msg, bool putPort = true) { putMedia(msg,m_rtpMedia,putPort); } + /** + * Retrieve a single media description + * @param name Name of the media to retrieve + * @return Pointer to media descriptor, NULL if no such media set + */ + SDPMedia* getMedia(const String& name) const + { return m_rtpMedia ? static_cast((*m_rtpMedia)[name]) : 0; } + + /** + * Update the RFC 2833 availability and payload + * @param value String to get payload or availability + */ + void setRfc2833(const String& value); + + /** + * Update the RFC 2833 availability and payload + * @param value Pointer to string to get payload or availability + */ + inline void setRfc2833(const String* value) + { if (value) setRfc2833(*value); } + /** * Build and dispatch a chan.rtp message for a given media. Update media on success * @param media The media to use @@ -523,8 +544,9 @@ public: /** * Reset this object to default values + * @param all True to reset all parameters including configuration */ - virtual void resetSdp(); + virtual void resetSdp(bool all = true); /** * Build a chan.rtp message and populate with media information @@ -566,6 +588,14 @@ public: static ObjList* updateRtpSDP(const NamedList& params, String& rtpAddr, ObjList* oldList = 0); +protected: + /** + * Media changed notification. + * This method is called when setting new media and an old one changed + * @param media Old media that changed + */ + virtual void mediaChanged(const SDPMedia& media); + SDPParser* m_parser; int m_mediaStatus; bool m_rtpForward; // Forward RTP flag @@ -578,15 +608,7 @@ public: int m_sdpVersion; // SDP version number, incremented each time we generate a new SDP String m_host; bool m_secure; - bool m_rfc2833; // Offer RFC 2833 to remote party - -protected: - /** - * Media changed notification. - * This method is called when setting new media and an old one changed - * @param media Old media that changed - */ - virtual void mediaChanged(const SDPMedia& media); + int m_rfc2833; // Payload of RFC 2833 for remote party }; /** @@ -605,8 +627,9 @@ public: * @param fmts Default media formats */ inline SDPParser(const char* dbgName, const char* sessName, const char* fmts = "alaw,mulaw") - : Mutex(true,"SDPParser"), m_sdpForward(false), - m_rfc2833(true), m_secure(false), m_ignorePort(false), + : Mutex(true,"SDPParser"), + m_rfc2833(101), + m_sdpForward(false), m_secure(false), m_ignorePort(false), m_sessionName(sessName), m_audioFormats(fmts), m_codecs(""), m_hacks("") { debugName(dbgName); } @@ -620,10 +643,10 @@ public: { Lock lock(this); buf = m_audioFormats; } /** - * Get the RFC 2833 offer flag - * @return True if RFC 2883 telephony events will be offered + * Get the RFC 2833 offer payload + * @return Payload for RFC 2883 telephony events, negative if not offered */ - inline bool rfc2833() const + inline int rfc2833() const { return m_rfc2833; } /** @@ -695,8 +718,8 @@ public: static const TokenDict s_rtpmap[]; private: + int m_rfc2833; // RFC 2833 payload offered to remote bool m_sdpForward; // Include raw SDP for forwarding - bool m_rfc2833; // Offer RFC 2833 to remote party bool m_secure; // Offer SRTP bool m_ignorePort; // Ignore port only changes in SDP String m_sessionName; diff --git a/modules/server/mgcpca.cpp b/modules/server/mgcpca.cpp index 16231b04..671fa88b 100644 --- a/modules/server/mgcpca.cpp +++ b/modules/server/mgcpca.cpp @@ -230,7 +230,7 @@ private: bool sendRequest(const char* sigReq, const char* reqEvt = 0, const char* digitMap = 0); bool sendPending(const char* sigReq = 0); bool enqueueEvent(SignallingCircuitEvent::Type type, const char* name, const char* dtmf = 0); - void cleanupRtp(); + void cleanupRtp(bool all = true); bool createRtp(); bool setupConn(const char* mode = 0); String m_epId; @@ -1271,9 +1271,9 @@ void* MGCPCircuit::getObject(const String& name) const } // Clean up any RTP we may still hold -void MGCPCircuit::cleanupRtp() +void MGCPCircuit::cleanupRtp(bool all) { - resetSdp(); + resetSdp(all); m_localRawSdp.clear(); m_localRtpChanged = false; m_remoteRawSdp.clear(); @@ -1286,8 +1286,7 @@ bool MGCPCircuit::createRtp() { if (hasRtp()) return true; - cleanupRtp(); - resetSdp(); + cleanupRtp(false); updateSDP(NamedList::empty()); RefPointer de = new DataEndpoint; bool ok = dispatchRtp(mySpan()->address(),false,de); @@ -1299,7 +1298,7 @@ bool MGCPCircuit::createRtp() } else { Debug(&splugin,DebugWarn,"MGCPCircuit::createRtp() failed [%p]",this); - cleanupRtp(); + cleanupRtp(false); } TelEngine::destruct(de); return ok; @@ -1377,7 +1376,7 @@ void MGCPCircuit::clearConn(bool force) } m_connId.clear(); m_specialMode.clear(); - resetSdp(); + resetSdp(false); m_remoteRawSdp.clear(); m_localRtpChanged = false; sendAsync(mm); @@ -1555,12 +1554,14 @@ bool MGCPCircuit::status(Status newStat, bool sync) m_consumer = 0; } else - cleanupRtp(); + cleanupRtp(false); } m_statusReq = SignallingCircuit::status(); m_changing = false; return false; case Reserved: + if (SignallingCircuit::status() <= Idle) + cleanupRtp(); break; case Idle: if (m_needClear) { @@ -1627,6 +1628,8 @@ bool MGCPCircuit::setParam(const String& param, const String& value) rtpChanged = m_rtpForward != fwd; m_rtpForward = fwd; } + else if (param == "rtp_rfc2833") + setRfc2833(value); else if (param == "special_mode") m_specialMode = value; else @@ -1844,7 +1847,7 @@ void MGCPCircuit::processDelete(MGCPMessage* mm, const String& error) m_connId.clear(); m_gwFormat = mySpan()->bearer(); m_gwFormatChanged = false; - cleanupRtp(); + cleanupRtp(false); m_changing = false; unsigned int code = 0; String tmp(error); @@ -2071,7 +2074,8 @@ void MGCPPlugin::initialize() Engine::install(new DTMFHandler); } } - m_parser.initialize(cfg.getSection("codecs"),cfg.getSection("hacks")); + m_parser.initialize(cfg.getSection("codecs"),cfg.getSection("hacks"), + cfg.getSection("general")); } void MGCPPlugin::genUpdate(Message& msg) diff --git a/modules/server/ysigchan.cpp b/modules/server/ysigchan.cpp index 9a25d9d4..3c4e53d1 100644 --- a/modules/server/ysigchan.cpp +++ b/modules/server/ysigchan.cpp @@ -941,6 +941,9 @@ bool SigChannel::startCall(Message& msg, String& trunks) else cic->setParam("echocancel",String::boolText(echo->toBoolean(true))); } + const char* rfc2833 = msg.getValue("rfc2833"); + if (rfc2833) + cic->setParam("rtp_rfc2833",rfc2833); m_rtpForward = cic->getBoolParam("rtp_forward") && msg.getBoolValue("rtp_forward"); if (m_rtpForward) { m_sdpForward = (0 != msg.getParam("sdp_raw")); diff --git a/modules/ysipchan.cpp b/modules/ysipchan.cpp index 2a1594ce..0a527934 100644 --- a/modules/ysipchan.cpp +++ b/modules/ysipchan.cpp @@ -1977,7 +1977,7 @@ YateSIPConnection::YateSIPConnection(Message& msg, const String& uri, const char m_inband = msg.getBoolValue("dtmfinband",s_inband); m_info = msg.getBoolValue("dtmfinfo",s_info); m_secure = msg.getBoolValue("secure",plugin.parser().secure()); - m_rfc2833 = msg.getBoolValue("rfc2833",plugin.parser().rfc2833()); + setRfc2833(msg.getParam("rfc2833")); m_rtpForward = msg.getBoolValue("rtp_forward"); m_user = msg.getValue("user"); m_line = msg.getValue("line"); @@ -3328,7 +3328,7 @@ bool YateSIPConnection::callRouted(Message& msg) // try to disable RTP forwarding earliest possible if (m_rtpForward && !msg.getBoolValue("rtp_forward")) m_rtpForward = false; - m_rfc2833 = msg.getBoolValue("rfc2833",m_rfc2833); + setRfc2833(msg.getParam("rfc2833")); Channel::callRouted(msg); Lock lock(driver()); if (m_tr && (m_tr->getState() == SIPTransaction::Process)) {