Avoid resetting started RTP when handling re-invite/update containing currently used codec.
git-svn-id: http://yate.null.ro/svn/yate/trunk@6420 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
80cfdf66de
commit
6031f15896
|
@ -66,6 +66,54 @@ const char* SDPMedia::fmtList() const
|
|||
return 0;
|
||||
}
|
||||
|
||||
// Compare this media with another one
|
||||
bool SDPMedia::sameAs(const SDPMedia* other, bool ignorePort, bool checkStarted) const
|
||||
{
|
||||
if (!other)
|
||||
return false;
|
||||
const SDPMedia& m = *other;
|
||||
if (m.transport() != m_transport)
|
||||
return false;
|
||||
if (m.remotePort() != m_rPort)
|
||||
return false;
|
||||
checkStarted = checkStarted && isStarted();
|
||||
if (!checkStarted) {
|
||||
return (m.formats() == m_formats) &&
|
||||
((ignorePort && m.remotePort() && m_rPort) || (m.remotePort() == m_rPort));
|
||||
}
|
||||
|
||||
// Check format
|
||||
ObjList* lst = m.formats().split(',',false);
|
||||
bool found = lst->find(m_format);
|
||||
TelEngine::destruct(lst);
|
||||
if (!found) {
|
||||
XDebug(DebugAll,"SDPMedia::sameAs(%p) format='%s' other_formats='%s': not found [%p]",
|
||||
other,m_format.c_str(),m.formats().c_str(),this);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check payload format
|
||||
int pLoad = SDPMedia::payloadMapping(mappings(),m_format);
|
||||
int oPLoad = SDPMedia::payloadMapping(m.mappings(),m_format);
|
||||
if (pLoad == -1 || oPLoad == -1 || pLoad != oPLoad) {
|
||||
XDebug(DebugAll,
|
||||
"SDPMedia::sameAs(%p) format='%s' pload=%d (%s) other_pload=%d (%s): not matched [%p]",
|
||||
other,m_format.c_str(),pLoad,mappings().c_str(),oPLoad,m.mappings().c_str(),this);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check RFC 2833
|
||||
if (m_rfc2833 != m.m_rfc2833) {
|
||||
XDebug(DebugAll,
|
||||
"SDPMedia::sameAs(%p) rfc2833=%s other_rfc2833=%s: not matched [%p]",
|
||||
other,m_rfc2833.c_str(),m.m_rfc2833.c_str(),this);
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Check crypto
|
||||
return true;
|
||||
}
|
||||
|
||||
// Update members with data taken from a SDP, return true if something changed
|
||||
bool SDPMedia::update(const char* formats, int rport, int lport, bool force)
|
||||
{
|
||||
|
@ -210,6 +258,40 @@ void SDPMedia::putMedia(NamedList& msg, bool putPort)
|
|||
}
|
||||
}
|
||||
|
||||
// Copy RTP related data from old media
|
||||
void SDPMedia::keepRtp(const SDPMedia& other)
|
||||
{
|
||||
m_formats = other.m_formats;
|
||||
m_format = other.m_format;
|
||||
m_rfc2833 = other.m_rfc2833;
|
||||
m_id = other.m_id;
|
||||
m_rPort = other.m_rPort;
|
||||
m_lPort = other.m_lPort;
|
||||
crypto(other.m_rCrypto,true);
|
||||
crypto(other.m_lCrypto,false);
|
||||
}
|
||||
|
||||
int SDPMedia::payloadMapping(const String& mappings, const String& fmt)
|
||||
{
|
||||
if (!(mappings && fmt))
|
||||
return -2;
|
||||
String tmp = fmt;
|
||||
tmp << "=";
|
||||
ObjList* lst = mappings.split(',',false);
|
||||
int payload = -2;
|
||||
for (ObjList* pl = lst; pl; pl = pl->next()) {
|
||||
String* mapping = static_cast<String*>(pl->get());
|
||||
if (!mapping)
|
||||
continue;
|
||||
if (mapping->startsWith(tmp)) {
|
||||
payload = mapping->substr(tmp.length()).toInteger(-1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
TelEngine::destruct(lst);
|
||||
return payload;
|
||||
}
|
||||
|
||||
}; // namespace TelEngine
|
||||
|
||||
/* vi: set ts=8 sw=4 sts=4 noet: */
|
||||
|
|
|
@ -56,7 +56,7 @@ SDPSession::~SDPSession()
|
|||
}
|
||||
|
||||
// Set new media list. Return true if changed
|
||||
bool SDPSession::setMedia(ObjList* media)
|
||||
bool SDPSession::setMedia(ObjList* media, bool preserveExisting)
|
||||
{
|
||||
if (media == m_rtpMedia)
|
||||
return false;
|
||||
|
@ -68,8 +68,19 @@ bool SDPSession::setMedia(ObjList* media)
|
|||
chg = false;
|
||||
for (ObjList* o = tmp->skipNull(); o; o = o->skipNext()) {
|
||||
SDPMedia* m = static_cast<SDPMedia*>(o->get());
|
||||
if (media && m->sameAs(static_cast<SDPMedia*>((*media)[*m]),m_parser->ignorePort()))
|
||||
continue;
|
||||
if (media) {
|
||||
ObjList* l = media->find(*m);
|
||||
SDPMedia* newMedia = l ? static_cast<SDPMedia*>(l->get()) : 0;
|
||||
if (newMedia && m->sameAs(newMedia,m_parser->ignorePort(),preserveExisting)) {
|
||||
if (preserveExisting && m->isStarted()) {
|
||||
XDebug(m_enabler,DebugAll,
|
||||
"SDPSession::setMedia(%p) keeping existing media='%s' format='%s' [%p]",
|
||||
media,m->c_str(),m->format().c_str(),m_ptr);
|
||||
newMedia->keepRtp(*m);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
chg = true;
|
||||
mediaChanged(*m);
|
||||
}
|
||||
|
@ -843,22 +854,10 @@ Message* SDPSession::buildChanRtp(SDPMedia* media, const char* addr, bool start,
|
|||
m->addParam("remoteip",addr);
|
||||
if (start) {
|
||||
m->addParam("remoteport",media->remotePort());
|
||||
String tmp = media->format();
|
||||
tmp << "=";
|
||||
ObjList* mappings = media->mappings().split(',',false);
|
||||
for (ObjList* pl = mappings; pl; pl = pl->next()) {
|
||||
String* mapping = static_cast<String*>(pl->get());
|
||||
if (!mapping)
|
||||
continue;
|
||||
if (mapping->startsWith(tmp)) {
|
||||
tmp = *mapping;
|
||||
tmp >> "=";
|
||||
m->addParam("payload",tmp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
int payload = SDPMedia::payloadMapping(media->mappings(),media->format());
|
||||
if (payload >= 0)
|
||||
m->addParam("payload",String(payload));
|
||||
m->addParam("evpayload",media->rfc2833());
|
||||
TelEngine::destruct(mappings);
|
||||
}
|
||||
if (m_secure) {
|
||||
if (media->remoteCrypto()) {
|
||||
|
|
|
@ -112,6 +112,13 @@ public:
|
|||
inline const String& suffix() const
|
||||
{ return m_suffix; }
|
||||
|
||||
/**
|
||||
* Check if media is started
|
||||
* @return True if started, false otherwise
|
||||
*/
|
||||
inline bool isStarted() const
|
||||
{ return m_id && m_transport && m_format && m_lPort; }
|
||||
|
||||
/**
|
||||
* Retrieve the media transport name
|
||||
* @return The media transport name
|
||||
|
@ -213,13 +220,10 @@ public:
|
|||
* Compare this media with another one
|
||||
* @param other The media to compare with
|
||||
* @param ignorePort Ignore differences caused only by port number
|
||||
* @param checkStarted Check started related parameters: true when media should be kept if started and matched
|
||||
* @return True if both media have the same formats, transport and remote port
|
||||
*/
|
||||
inline bool sameAs(const SDPMedia* other, bool ignorePort = false) const
|
||||
{ return other && (other->formats() == m_formats) &&
|
||||
(other->transport() == m_transport) &&
|
||||
((ignorePort && other->remotePort() && m_rPort) ||
|
||||
(other->remotePort() == m_rPort)); }
|
||||
bool sameAs(const SDPMedia* other, bool ignorePort = false, bool checkStarted = false) const;
|
||||
|
||||
/**
|
||||
* Check if local part of this media changed
|
||||
|
@ -289,6 +293,21 @@ public:
|
|||
*/
|
||||
void putMedia(NamedList& msg, bool putPort = true);
|
||||
|
||||
/**
|
||||
* Copy RTP related data from old media
|
||||
* @param msg Destination list
|
||||
* @param putPort True to add remote media port
|
||||
*/
|
||||
void keepRtp(const SDPMedia& other);
|
||||
|
||||
/**
|
||||
* Retrieve format mapping to payload
|
||||
* @param mappings Mappings list
|
||||
* @param fmt Format name
|
||||
* @return -1:incorrect mapping value, -2:format not found, payload number otherwise (>=0)
|
||||
*/
|
||||
static int payloadMapping(const String& mappings, const String& fmt);
|
||||
|
||||
private:
|
||||
bool m_audio;
|
||||
bool m_video;
|
||||
|
@ -373,9 +392,10 @@ public:
|
|||
/**
|
||||
* Set a new media list
|
||||
* @param media New media list
|
||||
* @param preserveExisting Try to preserve existing started media
|
||||
* @return True if media changed
|
||||
*/
|
||||
bool setMedia(ObjList* media);
|
||||
bool setMedia(ObjList* media, bool preserveExisting = false);
|
||||
|
||||
/**
|
||||
* Put specified media parameters into a list of parameters
|
||||
|
|
|
@ -7490,6 +7490,7 @@ bool YateSIPConnection::reInviteProxy(SIPTransaction* t, MimeSdpBody* sdp, int i
|
|||
bool audioChg = (getMedia(YSTRING("audio")) != 0);
|
||||
audioChg ^= ((*lst)[YSTRING("audio")] != 0);
|
||||
|
||||
bool keepExisting = true;
|
||||
Message ver("call.update");
|
||||
if (s_update_verify) {
|
||||
complete(ver);
|
||||
|
@ -7513,6 +7514,7 @@ bool YateSIPConnection::reInviteProxy(SIPTransaction* t, MimeSdpBody* sdp, int i
|
|||
m_reInviting = invite;
|
||||
return true;
|
||||
}
|
||||
keepExisting = ver.getBoolValue(YSTRING("keep_media"),keepExisting);
|
||||
}
|
||||
|
||||
if (m_rtpAddr != addr) {
|
||||
|
@ -7522,7 +7524,7 @@ bool YateSIPConnection::reInviteProxy(SIPTransaction* t, MimeSdpBody* sdp, int i
|
|||
if (!s_rtp_preserve)
|
||||
setMedia(0);
|
||||
}
|
||||
setMedia(lst);
|
||||
setMedia(lst,keepExisting);
|
||||
|
||||
m_mediaStatus = MediaMissing;
|
||||
// let RTP guess again the local interface or use the enforced address
|
||||
|
|
Loading…
Reference in New Issue