Use the new SDP library in SIP and MGCP.
The PSTN channel can negotiate RTP forwarding if the circuits are terminated on a MGCP gateway. git-svn-id: http://voip.null.ro/svn/yate@2805 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
5b8b3431c6
commit
aaa1c2048d
|
@ -37,6 +37,72 @@
|
|||
;port=
|
||||
|
||||
|
||||
[codecs]
|
||||
; This section allows to individually enable or disable the codecs
|
||||
|
||||
; default: bool: Enable all unlisted codecs by default if a transcoder exists
|
||||
;default=enable
|
||||
|
||||
; mulaw: bool: Companded-only G711 mu-law (PCMU/8000)
|
||||
;mulaw=default
|
||||
|
||||
; alaw: bool: Companded-only G711 a-law (PCMU/8000)
|
||||
;alaw=default
|
||||
|
||||
; gsm: bool: European GSM 06.10 (GSM/8000)
|
||||
;gsm=default
|
||||
|
||||
; lpc10: bool: Linear Prediction Codec (LPC/8000)
|
||||
;lpc10=default
|
||||
|
||||
; ilbc: bool: Internet Low Bandwidth Codec (iLBC/8000)
|
||||
;ilbc=default
|
||||
|
||||
; amr: bool: Adaptive Multi-Rate 3GPP (AMR/8000)
|
||||
;amr=default
|
||||
|
||||
; slin: bool: Signed Linear 16-bit uncompressed (L16/8000)
|
||||
;slin=default
|
||||
|
||||
; g723: bool: ITU G.723 all variations (G723/8000)
|
||||
;g723=default
|
||||
|
||||
; g726: bool: ITU G.726 32-bit (G726-32/8000)
|
||||
;g726=default
|
||||
|
||||
; g728: bool: ITU G.728 all variations (G728/8000)
|
||||
;g728=default
|
||||
|
||||
; g729: bool: ITU G.729 all variations (G729/8000)
|
||||
;g729=default
|
||||
|
||||
; g729_annexb: bool: G.729 Annex B (VAD) support default (if not in SDP)
|
||||
; NOTE: RFC 3555 specifies the default should be yes
|
||||
;g729_annexb=no
|
||||
|
||||
; amr_octet: bool: Octet aligned AMR RTP payload default (if not in SDP)
|
||||
; NOTE: RFC 4867 (and older 3267) specifies the default is bandwidth efficient
|
||||
;amr_octet=no
|
||||
|
||||
|
||||
[hacks]
|
||||
; This section holds the dirty stuff required to work with some broken
|
||||
; implementations
|
||||
;
|
||||
; ilbc_forced: string: Format to force as iLBC, can be: ilbc20 or ilbc30
|
||||
;ilbc_forced=
|
||||
;
|
||||
; ilbc_default: string: Format to use for iLBC when packetization is unknown
|
||||
;ilbc_default=ilbc30
|
||||
|
||||
; g729_annexb: bool: Force G.729 Annex B support when parsing the SDP
|
||||
;g729_annexb=
|
||||
|
||||
; ignore_sdp_port: bool: Ignore SDP changes if only the port is different
|
||||
; This allows preserving the local RTP session and port
|
||||
;ignore_sdp_port=no
|
||||
|
||||
|
||||
;[gw PUT_NAME_HERE]
|
||||
; One gw ... section is required for each gateway we control
|
||||
; The gateway name is a string that can be referenced from other modules
|
||||
|
@ -80,3 +146,10 @@
|
|||
|
||||
; clearconn: bool: Clear all connections of remote endpoints when initialized
|
||||
;clearconn=no
|
||||
|
||||
; forward_rtp: bool: Support to forward RTP directly to protocols that support it
|
||||
; The actual direct RTP forwarding is still negotiated in routing
|
||||
;forward_rtp=yes for digital gateways, no for analogic
|
||||
|
||||
; forward_sdp: bool: Also include the raw SDP in the RTP forward offer
|
||||
;forward_sdp=no
|
||||
|
|
|
@ -248,18 +248,18 @@ yjinglechan.yate jingle/jinglefeatures.yate: LOCALLIBS = -lyatejingle
|
|||
|
||||
server/dbpbx.yate server/pbxassist.yate: ../libs/ypbx/libyatepbx.a
|
||||
server/dbpbx.yate server/pbxassist.yate: LOCALFLAGS = -I@top_srcdir@/libs/ypbx
|
||||
server/dbpbx.yate server/pbxassist.yate: LOCALLIBS = ../libs/ypbx/libyatepbx.a
|
||||
server/dbpbx.yate server/pbxassist.yate: LOCALLIBS = -L../libs/ypbx -lyatepbx
|
||||
|
||||
server/mgcpca.yate: ../libyatemgcp.so ../libyatesig.so
|
||||
server/mgcpca.yate: LOCALFLAGS = -I@top_srcdir@/libs/ymgcp -I@top_srcdir@/libs/ysig
|
||||
server/mgcpca.yate: LOCALLIBS = -lyatemgcp -lyatesig
|
||||
server/mgcpca.yate: ../libyatemgcp.so ../libyatesig.so ../libs/ysdp/libyatesdp.a
|
||||
server/mgcpca.yate: LOCALFLAGS = -I@top_srcdir@/libs/ymgcp -I@top_srcdir@/libs/ysig -I@top_srcdir@/libs/ysdp
|
||||
server/mgcpca.yate: LOCALLIBS = -lyatemgcp -lyatesig -L../libs/ysdp -lyatesdp
|
||||
|
||||
server/mgcpgw.yate: ../libyatemgcp.so
|
||||
server/mgcpgw.yate: LOCALFLAGS = -I@top_srcdir@/libs/ymgcp
|
||||
server/mgcpgw.yate: LOCALLIBS = -lyatemgcp
|
||||
|
||||
ilbccodec.yate: ../libs/ilbc/libilbc.a
|
||||
ilbccodec.yate: LOCALLIBS = ../libs/ilbc/libilbc.a
|
||||
ilbccodec.yate: LOCALLIBS = -L../libs/ilbc -lilbc
|
||||
ilbccodec.yate: LOCALFLAGS = @ILBC_INC@
|
||||
|
||||
gsmcodec.yate: LOCALLIBS = -lgsm
|
||||
|
@ -274,13 +274,13 @@ amrnbcodec.yate: LOCALLIBS = @AMRNB_LIB@
|
|||
faxchan.yate: LOCALLIBS = -lspandsp
|
||||
faxchan.yate: LOCALFLAGS = @SPANDSP_INC@
|
||||
|
||||
ysipchan.yate: ../libs/ysip/libyatesip.a
|
||||
ysipchan.yate: LOCALFLAGS = -I@top_srcdir@/libs/ysip
|
||||
ysipchan.yate: LOCALLIBS = ../libs/ysip/libyatesip.a
|
||||
ysipchan.yate: ../libs/ysip/libyatesip.a ../libs/ysdp/libyatesdp.a
|
||||
ysipchan.yate: LOCALFLAGS = -I@top_srcdir@/libs/ysip -I@top_srcdir@/libs/ysdp
|
||||
ysipchan.yate: LOCALLIBS = -L../libs/ysip -lyatesip -L../libs/ysdp -lyatesdp
|
||||
|
||||
yrtpchan.yate: ../libs/yrtp/libyatertp.a
|
||||
yrtpchan.yate: LOCALFLAGS = -I@top_srcdir@/libs/yrtp
|
||||
yrtpchan.yate: LOCALLIBS = ../libs/yrtp/libyatertp.a
|
||||
yrtpchan.yate: LOCALLIBS = -L../libs/yrtp -lyatertp
|
||||
|
||||
openssl.yate: LOCALFLAGS = @OPENSSL_INC@
|
||||
openssl.yate: LOCALLIBS = @OPENSSL_LIB@
|
||||
|
@ -304,6 +304,9 @@ qt4/updater.yate: LOCALLIBS = @QT4_LIB_NET@
|
|||
../libs/yrtp/libyatertp.a:
|
||||
$(MAKE) -C ../libs/yrtp
|
||||
|
||||
../libs/ysdp/libyatesdp.a:
|
||||
$(MAKE) -C ../libs/ysdp
|
||||
|
||||
../libs/yiax/libyateiax.a:
|
||||
$(MAKE) -C ../libs/yiax
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <yatephone.h>
|
||||
#include <yatemgcp.h>
|
||||
#include <yatesig.h>
|
||||
#include <yatesdp.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -112,6 +113,7 @@ public:
|
|||
bool ownsId(const String& rqId) const;
|
||||
static SignallingComponent* create(const String& type, const NamedList& name);
|
||||
static MGCPSpan* findNotify(const String& id);
|
||||
bool getBoolParam(const String& param, bool defValue) const;
|
||||
bool matchEndpoint(const MGCPEndpointId& ep);
|
||||
bool processEvent(MGCPTransaction* tr, MGCPMessage* mm);
|
||||
bool processNotify(MGCPTransaction* tr, MGCPMessage* mm, const String& event, const String& requestId);
|
||||
|
@ -127,6 +129,8 @@ private:
|
|||
unsigned int m_count;
|
||||
MGCPEndpointId m_epId;
|
||||
bool m_operational;
|
||||
bool m_rtpForward;
|
||||
bool m_sdpForward;
|
||||
bool m_fxo;
|
||||
bool m_fxs;
|
||||
String m_notify;
|
||||
|
@ -134,7 +138,7 @@ private:
|
|||
String m_version;
|
||||
};
|
||||
|
||||
class MGCPCircuit : public SignallingCircuit
|
||||
class MGCPCircuit : public SignallingCircuit, public SDPSession
|
||||
{
|
||||
public:
|
||||
MGCPCircuit(unsigned int code, MGCPSpan* span, const char* id);
|
||||
|
@ -142,6 +146,11 @@ public:
|
|||
virtual void* getObject(const String& name) const;
|
||||
virtual bool status(Status newStat, bool sync);
|
||||
virtual bool updateFormat(const char* format, int direction);
|
||||
virtual bool setParam(const String& param, const String& value);
|
||||
virtual bool getParam(const String& param, String& value) const;
|
||||
virtual bool getBoolParam(const String& param, bool defValue) const;
|
||||
virtual bool setParams(const NamedList& params);
|
||||
virtual bool getParams(NamedList& params, const String& category = String::empty());
|
||||
virtual bool sendEvent(SignallingCircuitEvent::Type type, NamedList* params);
|
||||
inline const String& epId() const
|
||||
{ return m_epId; }
|
||||
|
@ -150,12 +159,16 @@ public:
|
|||
inline const String& connId() const
|
||||
{ return m_connId; }
|
||||
inline bool hasRtp() const
|
||||
{ return m_rtpId && (m_source || m_consumer); }
|
||||
{ return m_source || m_consumer; }
|
||||
inline bool hasLocalRtp() const
|
||||
{ return m_rtpLocalAddr || m_localRawSdp; }
|
||||
inline MGCPSpan* mySpan()
|
||||
{ return static_cast<MGCPSpan*>(span()); }
|
||||
inline bool fxo()
|
||||
inline const MGCPSpan* mySpan() const
|
||||
{ return static_cast<const MGCPSpan*>(span()); }
|
||||
inline bool fxo() const
|
||||
{ return mySpan()->fxo(); }
|
||||
inline bool fxs()
|
||||
inline bool fxs() const
|
||||
{ return mySpan()->fxs(); }
|
||||
inline void needClear()
|
||||
{ m_needClear = true; }
|
||||
|
@ -163,7 +176,26 @@ public:
|
|||
bool processNotify(const String& package, const String& event, const String& fullName);
|
||||
void processDelete(MGCPMessage* mm, const String& error);
|
||||
void clearConn(bool force = false);
|
||||
protected:
|
||||
// Create a chan.rtp message pointing to the circuit
|
||||
virtual Message* buildChanRtp(RefObject* context)
|
||||
{
|
||||
Message* m = new Message("chan.rtp");
|
||||
m->userData(context ? context : this);
|
||||
return m;
|
||||
}
|
||||
virtual Message* buildChanRtp(SDPMedia* media, const char* addr, bool start, RefObject* context)
|
||||
{
|
||||
Message* m = SDPSession::buildChanRtp(media,addr,start,context);
|
||||
if (m) {
|
||||
if (start && media->id())
|
||||
m->addParam("rtpid",media->id());
|
||||
m->addParam("mgcp_allowed",String::boolText(false));
|
||||
}
|
||||
return m;
|
||||
}
|
||||
private:
|
||||
void waitNotChanging();
|
||||
MGCPMessage* message(const char* cmd);
|
||||
bool sendAsync(MGCPMessage* mm);
|
||||
RefPointer<MGCPMessage> sendSync(MGCPMessage* mm);
|
||||
|
@ -171,28 +203,25 @@ private:
|
|||
bool enqueueEvent(SignallingCircuitEvent::Type type, const char* name, const char* dtmf = 0);
|
||||
void cleanupRtp();
|
||||
bool createRtp();
|
||||
bool startRtp();
|
||||
bool setupConn();
|
||||
String m_epId;
|
||||
Status m_statusReq;
|
||||
String m_notify;
|
||||
bool m_changing;
|
||||
// Gateway endpoint bearer information
|
||||
String m_gwFormat;
|
||||
bool m_gwFormatChanged;
|
||||
// Connection data
|
||||
String m_connId;
|
||||
String m_callId;
|
||||
// Local RTP related data
|
||||
RefPointer<DataSource> m_source;
|
||||
RefPointer<DataConsumer> m_consumer;
|
||||
String m_rtpId;
|
||||
String m_localIp;
|
||||
int m_localPort;
|
||||
int m_sdpSession;
|
||||
int m_sdpVersion;
|
||||
String m_localRawSdp;
|
||||
bool m_localRtpChanged;
|
||||
// Remote (MGCP GW side) RTP data
|
||||
String m_remoteIp;
|
||||
int m_remotePort;
|
||||
int m_remotePayload;
|
||||
const char* m_payloads;
|
||||
bool m_needClear;
|
||||
String m_remoteRawSdp;
|
||||
// Synchronous transaction data
|
||||
MGCPTransaction* m_tr;
|
||||
RefPointer<MGCPMessage> m_msg;
|
||||
|
@ -227,12 +256,14 @@ public:
|
|||
virtual void initialize();
|
||||
virtual void statusParams(String& str);
|
||||
virtual void statusDetail(String& str);
|
||||
inline SDPParser& parser()
|
||||
{ return m_parser; }
|
||||
private:
|
||||
SDPParser m_parser;
|
||||
};
|
||||
|
||||
YSIGFACTORY2(MGCPSpan);
|
||||
|
||||
static const char* s_payloads = "0 8";
|
||||
|
||||
static YMGCPEngine* s_engine = 0;
|
||||
static MGCPEndpoint* s_endpoint = 0;
|
||||
static String s_defaultEp;
|
||||
|
@ -242,6 +273,40 @@ static ObjList s_wrappers;
|
|||
static ObjList s_spans;
|
||||
static Mutex s_mutex(false,"MGCP-CA");
|
||||
|
||||
// Yate Payloads for the AV profile
|
||||
static TokenDict s_dict_payloads[] = {
|
||||
{ "mulaw", 0 },
|
||||
{ "alaw", 8 },
|
||||
{ "gsm", 3 },
|
||||
{ "lpc10", 7 },
|
||||
{ "slin", 11 },
|
||||
{ "g726", 2 },
|
||||
{ "g722", 9 },
|
||||
{ "g723", 4 },
|
||||
{ "g728", 15 },
|
||||
{ "g729", 18 },
|
||||
{ "ilbc", 98 },
|
||||
{ "ilbc20", 98 },
|
||||
{ "ilbc30", 98 },
|
||||
{ "amr", 96 },
|
||||
{ "amr-o", 96 },
|
||||
{ "amr/16000", 99 },
|
||||
{ "amr-o/16000", 99 },
|
||||
{ "speex", 102 },
|
||||
{ "speex/16000", 103 },
|
||||
{ "speex/32000", 104 },
|
||||
{ "h261", 31 },
|
||||
{ "h263", 34 },
|
||||
{ "mpv", 32 },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
// Media gateway bearer information (mapped from s_dict_payloads)
|
||||
static TokenDict s_dict_gwbearerinfo[] = {
|
||||
{ "e:mu", 0 },
|
||||
{ "e:A", 8 },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
// Copy one parameter (if present) with new name
|
||||
static bool copyRename(NamedList& dest, const char* dname, const NamedList& src, const String& sname)
|
||||
|
@ -742,7 +807,7 @@ MGCPSpan::MGCPSpan(const NamedList& params, const char* name, const MGCPEpInfo&
|
|||
: SignallingCircuitSpan(params.getValue("debugname",name),
|
||||
static_cast<SignallingCircuitGroup*>(params.getObject("SignallingCircuitGroup"))),
|
||||
m_circuits(0), m_count(0), m_epId(ep), m_operational(false),
|
||||
m_fxo(false), m_fxs(false)
|
||||
m_rtpForward(false), m_sdpForward(false), m_fxo(false), m_fxs(false)
|
||||
{
|
||||
Debug(&splugin,DebugAll,"MGCPSpan::MGCPSpan(%p,'%s') [%p]",
|
||||
¶ms,name,this);
|
||||
|
@ -824,6 +889,8 @@ bool MGCPSpan::init(const NamedList& params)
|
|||
break;
|
||||
}
|
||||
m_increment = config->getIntValue("increment",m_increment);
|
||||
m_rtpForward = config->getBoolValue("forward_rtp",!(m_fxo || m_fxs));
|
||||
m_sdpForward = config->getBoolValue("forward_sdp",false);
|
||||
bool clear = config->getBoolValue("clearconn",false);
|
||||
m_circuits = new MGCPCircuit*[m_count];
|
||||
unsigned int i;
|
||||
|
@ -897,6 +964,18 @@ void MGCPSpan::operational(const SocketAddr& address)
|
|||
operational(true);
|
||||
}
|
||||
|
||||
// Get a configuration or operational boolean parameter by name
|
||||
bool MGCPSpan::getBoolParam(const String& param, bool defValue) const
|
||||
{
|
||||
if (param == "operational")
|
||||
return operational();
|
||||
if (param == "rtp_forward")
|
||||
return m_rtpForward;
|
||||
if (param == "sdp_forward")
|
||||
return m_sdpForward;
|
||||
return defValue;
|
||||
}
|
||||
|
||||
// Check if this span matches an endpoint ID
|
||||
bool MGCPSpan::matchEndpoint(const MGCPEndpointId& ep)
|
||||
{
|
||||
|
@ -1048,10 +1127,9 @@ bool MGCPSpan::processDelete(MGCPTransaction* tr, MGCPMessage* mm, const String&
|
|||
|
||||
MGCPCircuit::MGCPCircuit(unsigned int code, MGCPSpan* span, const char* id)
|
||||
: SignallingCircuit(RTP,code,Missing,span->group(),span),
|
||||
m_epId(id), m_statusReq(Missing),
|
||||
m_localPort(0), m_sdpSession(0), m_sdpVersion(0),
|
||||
m_remotePort(0), m_remotePayload(-1),
|
||||
m_payloads(s_payloads), m_needClear(false), m_tr(0)
|
||||
SDPSession(&splugin.parser()),
|
||||
m_epId(id), m_statusReq(Missing), m_changing(false), m_gwFormatChanged(false),
|
||||
m_localRtpChanged(false), m_needClear(false), m_tr(0)
|
||||
{
|
||||
Debug(&splugin,DebugAll,"MGCPCircuit::MGCPCircuit(%u,%p,'%s') [%p]",
|
||||
code,span,id,this);
|
||||
|
@ -1093,11 +1171,10 @@ void* MGCPCircuit::getObject(const String& name) const
|
|||
// Clean up any RTP we may still hold
|
||||
void MGCPCircuit::cleanupRtp()
|
||||
{
|
||||
if (m_rtpId) {
|
||||
m_rtpId.clear();
|
||||
m_localIp.clear();
|
||||
m_localPort = 0;
|
||||
}
|
||||
resetSdp();
|
||||
m_localRawSdp.clear();
|
||||
m_localRtpChanged = false;
|
||||
m_remoteRawSdp.clear();
|
||||
m_source = 0;
|
||||
m_consumer = 0;
|
||||
}
|
||||
|
@ -1108,54 +1185,22 @@ bool MGCPCircuit::createRtp()
|
|||
if (hasRtp())
|
||||
return true;
|
||||
cleanupRtp();
|
||||
Message m("chan.rtp");
|
||||
resetSdp();
|
||||
updateSDP(NamedList::empty());
|
||||
RefPointer<DataEndpoint> de = new DataEndpoint;
|
||||
de->deref();
|
||||
m.userData(de);
|
||||
m.addParam("direction","bidir");
|
||||
if (m_remoteIp && m_remotePort) {
|
||||
m.addParam("remoteip",m_remoteIp);
|
||||
m.addParam("remoteport",String(m_remotePort));
|
||||
}
|
||||
else
|
||||
m.addParam("remoteip",mySpan()->address());
|
||||
m.addParam("mgcp_allowed",String::boolText(false));
|
||||
if (Engine::dispatch(m)) {
|
||||
bool ok = dispatchRtp(mySpan()->address(),false,de);
|
||||
if (ok) {
|
||||
m_source = de->getSource();
|
||||
m_consumer = de->getConsumer();
|
||||
m_rtpId = m.getValue("rtpid");
|
||||
m_localIp = m.getValue("localip");
|
||||
m_localPort = m.getIntValue("localport");
|
||||
if (m_localIp && m_localPort && hasRtp())
|
||||
return true;
|
||||
DDebug(&splugin,DebugAll,"MGCPCircuit::createRtp() src=%p cons=%p [%p]",
|
||||
(void*)m_source,(void*)m_consumer,this);
|
||||
}
|
||||
m_localIp.clear();
|
||||
m_localPort = 0;
|
||||
Debug(&splugin,DebugWarn,"MGCPCircuit::createRtp() failed [%p]",this);
|
||||
cleanupRtp();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Start the local RTP instance
|
||||
bool MGCPCircuit::startRtp()
|
||||
{
|
||||
if (!(m_remoteIp && m_remotePort && (m_remotePayload >= 0) && hasRtp()))
|
||||
return false;
|
||||
Message m("chan.rtp");
|
||||
m.addParam("direction","bidir");
|
||||
m.addParam("rtpid",m_rtpId);
|
||||
m.addParam("remoteip",m_remoteIp);
|
||||
m.addParam("remoteport",String(m_remotePort));
|
||||
m.addParam("payload",String(m_remotePayload));
|
||||
if (m_localIp)
|
||||
m.addParam("localip",m_localIp);
|
||||
if (m_localPort)
|
||||
m.addParam("localport",String(m_localPort));
|
||||
m.addParam("mgcp_allowed",String::boolText(false));
|
||||
if (Engine::dispatch(m))
|
||||
return true;
|
||||
Debug(&splugin,DebugWarn,"MGCPCircuit::startRtp() failed [%p]",this);
|
||||
return false;
|
||||
else {
|
||||
Debug(&splugin,DebugWarn,"MGCPCircuit::createRtp() failed [%p]",this);
|
||||
cleanupRtp();
|
||||
}
|
||||
TelEngine::destruct(de);
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Create or update remote connection
|
||||
|
@ -1165,61 +1210,41 @@ bool MGCPCircuit::setupConn()
|
|||
mm->params.addParam("C",m_callId);
|
||||
if (m_connId)
|
||||
mm->params.addParam("I",m_connId);
|
||||
if (m_localIp && m_localPort) {
|
||||
if (m_gwFormatChanged && m_gwFormat)
|
||||
mm->params.addParam("B",m_gwFormat);
|
||||
if (m_localRawSdp) {
|
||||
mm->params.addParam("M","sendrecv");
|
||||
if (m_sdpSession)
|
||||
++m_sdpVersion;
|
||||
else
|
||||
m_sdpSession = m_sdpVersion = Time::secNow();
|
||||
String mLine("audio ");
|
||||
String oLine("yate ");
|
||||
mLine << m_localPort << " RTP/AVP " << m_payloads;
|
||||
oLine << m_sdpSession << " " << m_sdpVersion << " IN IP4 " << m_localIp;
|
||||
MimeSdpBody* sdp = new MimeSdpBody;
|
||||
sdp->addLine("v","0");
|
||||
sdp->addLine("o",oLine);
|
||||
sdp->addLine("s","PSTN Circuit");
|
||||
sdp->addLine("c","IN IP4 " + m_localIp);
|
||||
sdp->addLine("t","0 0");
|
||||
sdp->addLine("m",mLine);
|
||||
mm->sdp.append(sdp);
|
||||
mm->sdp.append(new MimeSdpBody("application/sdp",
|
||||
m_localRawSdp.safe(),m_localRawSdp.length()));
|
||||
}
|
||||
else {
|
||||
MimeSdpBody* sdp = createSDP(getRtpAddr());
|
||||
if (sdp) {
|
||||
mm->params.addParam("M","sendrecv");
|
||||
mm->sdp.append(sdp);
|
||||
}
|
||||
}
|
||||
mm = sendSync(mm);
|
||||
if (!mm)
|
||||
return false;
|
||||
m_gwFormatChanged = false;
|
||||
if (m_connId.null())
|
||||
m_connId = mm->params.getParam("i");
|
||||
if (m_connId.null()) {
|
||||
m_needClear = true;
|
||||
return false;
|
||||
}
|
||||
m_localRtpChanged = false;
|
||||
MimeSdpBody* sdp = static_cast<MimeSdpBody*>(mm->sdp[0]);
|
||||
if (sdp) {
|
||||
m_remoteIp.clear();
|
||||
m_remotePort = 0;
|
||||
const NamedString* c = sdp->getLine("c");
|
||||
if (c) {
|
||||
String tmp(*c);
|
||||
if (tmp.startSkip("IN IP4")) {
|
||||
tmp.trimBlanks();
|
||||
if (tmp == "0.0.0.0")
|
||||
tmp.clear();
|
||||
m_remoteIp = tmp;
|
||||
}
|
||||
}
|
||||
c = sdp->getLine("m");
|
||||
for (; c; c = sdp->getNextLine(c)) {
|
||||
String tmp(*c);
|
||||
if (!tmp.startSkip("audio",true))
|
||||
continue;
|
||||
int port = 0;
|
||||
tmp >> port >> " ";
|
||||
if (!tmp.startSkip("RTP/AVP",true,true))
|
||||
continue;
|
||||
m_remotePort = port;
|
||||
tmp >> m_remotePayload;
|
||||
return (m_remotePayload >= 0) && (m_remotePayload <= 255);
|
||||
}
|
||||
String oldIp = m_rtpAddr;
|
||||
bool mediaChanged = setMedia(splugin.parser().parse(*sdp,m_rtpAddr,m_rtpMedia));
|
||||
const DataBlock& raw = sdp->getBody();
|
||||
m_remoteRawSdp.assign((const char*)raw.data(),raw.length());
|
||||
// Disconnect if media changed
|
||||
if (mediaChanged && oldIp && oldIp != m_rtpAddr)
|
||||
enqueueEvent(SignallingCircuitEvent::Disconnected,"Disconnected");
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1236,13 +1261,31 @@ void MGCPCircuit::clearConn(bool force)
|
|||
}
|
||||
if (!force)
|
||||
mm->params.addParam("C",m_callId);
|
||||
else {
|
||||
m_gwFormat.clear();
|
||||
m_gwFormatChanged = false;
|
||||
}
|
||||
m_connId.clear();
|
||||
m_remoteIp.clear();
|
||||
m_remotePort = 0;
|
||||
m_sdpSession = 0;
|
||||
resetSdp();
|
||||
m_remoteRawSdp.clear();
|
||||
m_localRtpChanged = false;
|
||||
sendAsync(mm);
|
||||
}
|
||||
|
||||
// Wait for changing flag to be false
|
||||
void MGCPCircuit::waitNotChanging()
|
||||
{
|
||||
while (true) {
|
||||
Lock lock(s_mutex);
|
||||
if (!m_changing) {
|
||||
m_changing = true;
|
||||
break;
|
||||
}
|
||||
lock.drop();
|
||||
Thread::yield(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Build a MGCP message
|
||||
MGCPMessage* MGCPCircuit::message(const char* cmd)
|
||||
{
|
||||
|
@ -1308,32 +1351,65 @@ bool MGCPCircuit::sendRequest(const char* sigReq, const char* reqEvt, const char
|
|||
// Circuit status change request
|
||||
bool MGCPCircuit::status(Status newStat, bool sync)
|
||||
{
|
||||
Debug(&splugin,DebugInfo,"MGCPCircuit::status(%s,%s) [%p]",
|
||||
lookupStatus(newStat),String::boolText(sync),this);
|
||||
if ((newStat == m_statusReq) && ((SignallingCircuit::status() == newStat) || !sync))
|
||||
return true;
|
||||
if (!mySpan()->operational()) {
|
||||
if (newStat >= Idle)
|
||||
Debug(&splugin,DebugInfo,"MGCPCircuit::status(%s,%s) %u [%p]",
|
||||
lookupStatus(newStat),String::boolText(sync),code(),this);
|
||||
waitNotChanging();
|
||||
// Don't notify local rtp if we already have it (addr/port/sdp) and didn't changed
|
||||
// Accept only synchronous connect requests
|
||||
bool allowRtpChange = false;
|
||||
if (newStat == Connected) {
|
||||
if (!sync) {
|
||||
m_changing = false;
|
||||
return false;
|
||||
}
|
||||
allowRtpChange = SignallingCircuit::status() == Connected &&
|
||||
hasLocalRtp() && m_localRtpChanged;
|
||||
if (SignallingCircuit::status() != Connected && !(fxs() || fxo()))
|
||||
sendRequest(0,"D/[0-9#*](N)");
|
||||
}
|
||||
if (!allowRtpChange && (newStat == m_statusReq) &&
|
||||
((SignallingCircuit::status() == newStat) || !sync)) {
|
||||
m_changing = false;
|
||||
return true;
|
||||
}
|
||||
if (!mySpan()->operational()) {
|
||||
if (newStat >= Idle) {
|
||||
m_changing = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
m_statusReq = newStat;
|
||||
switch (newStat) {
|
||||
case Connected:
|
||||
if (createRtp() && setupConn() && startRtp())
|
||||
break;
|
||||
// Create local rtp if we don't have one
|
||||
// Start it if we don't forward the rtp
|
||||
if (m_rtpForward || hasLocalRtp() || createRtp()) {
|
||||
if (setupConn()) {
|
||||
if (m_rtpForward || startRtp())
|
||||
break;
|
||||
clearConn();
|
||||
}
|
||||
cleanupRtp();
|
||||
}
|
||||
m_statusReq = SignallingCircuit::status();
|
||||
m_changing = false;
|
||||
return false;
|
||||
case Reserved:
|
||||
break;
|
||||
case Idle:
|
||||
if (m_needClear) {
|
||||
m_needClear = false;
|
||||
clearConn(true);
|
||||
}
|
||||
default:
|
||||
m_payloads = s_payloads;
|
||||
cleanupRtp();
|
||||
clearConn();
|
||||
}
|
||||
return SignallingCircuit::status(newStat,sync);
|
||||
DDebug(&splugin,DebugInfo,"MGCPCircuit new status '%s' on %u [%p]",
|
||||
lookupStatus(newStat),code(),this);
|
||||
bool ok = SignallingCircuit::status(newStat,sync);
|
||||
m_changing = false;
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Change the format of this circuit
|
||||
|
@ -1343,12 +1419,99 @@ bool MGCPCircuit::updateFormat(const char* format, int direction)
|
|||
return false;
|
||||
Debug(&splugin,DebugInfo,"MGCPCircuit::updateFormat('%s',%d) %u [%p]",
|
||||
format,direction,code(),this);
|
||||
if (0 == ::strcmp(format,"mulaw"))
|
||||
m_payloads = "0";
|
||||
else if (0 == ::strcmp(format,"alaw"))
|
||||
m_payloads = "8";
|
||||
int fmt = lookup(format,s_dict_payloads,-1);
|
||||
const char* gwFmt = lookup(fmt,s_dict_gwbearerinfo);
|
||||
if (!gwFmt)
|
||||
return false;
|
||||
waitNotChanging();
|
||||
if (m_gwFormat != gwFmt) {
|
||||
m_gwFormat = gwFmt;
|
||||
m_gwFormatChanged = true;
|
||||
}
|
||||
m_changing = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MGCPCircuit::setParam(const String& param, const String& value)
|
||||
{
|
||||
if (m_changing)
|
||||
return false;
|
||||
Lock lock(s_mutex);
|
||||
if (m_changing)
|
||||
return false;
|
||||
bool rtpChanged = false;
|
||||
if (param == "sdp_raw") {
|
||||
rtpChanged = m_localRawSdp != value;
|
||||
m_localRawSdp = value;
|
||||
}
|
||||
else if (param == "rtp_forward") {
|
||||
bool fwd = value.toBoolean();
|
||||
rtpChanged = m_rtpForward != fwd;
|
||||
m_rtpForward = fwd;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
m_localRtpChanged = m_localRtpChanged || rtpChanged;
|
||||
lock.drop();
|
||||
DDebug(&splugin,DebugAll,"MGCPCircuit::setParam(%s,%s) %u [%p]",
|
||||
param.c_str(),value.c_str(),code(),this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MGCPCircuit::getParam(const String& param, String& value) const
|
||||
{
|
||||
if (m_changing)
|
||||
return false;
|
||||
Lock lock(s_mutex);
|
||||
if (m_changing)
|
||||
return false;
|
||||
if (param == "rtp_addr") {
|
||||
value = m_rtpAddr;
|
||||
return true;
|
||||
}
|
||||
else if (param == "sdp_raw") {
|
||||
value = m_remoteRawSdp;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MGCPCircuit::getBoolParam(const String& param, bool defValue) const
|
||||
{
|
||||
return mySpan()->getBoolParam(param,defValue);
|
||||
}
|
||||
|
||||
// Set circuit data from a list of parameters
|
||||
bool MGCPCircuit::setParams(const NamedList& params)
|
||||
{
|
||||
if (params == "rtp") {
|
||||
waitNotChanging();
|
||||
DDebug(&splugin,DebugAll,"MGCPCircuit::setParams(rtp) %u [%p]",code(),this);
|
||||
String* raw = params.getParam("sdp_raw");
|
||||
if (raw && m_localRawSdp != *raw) {
|
||||
m_localRawSdp = *raw;
|
||||
m_localRtpChanged = true;
|
||||
m_rtpForward = true;
|
||||
}
|
||||
if (!m_localRawSdp) {
|
||||
m_localRtpChanged = updateRtpSDP(params) || localRtpChanged() || m_localRtpChanged;
|
||||
setLocalRtpChanged();
|
||||
if (m_localRtpChanged)
|
||||
m_rtpForward = true;
|
||||
}
|
||||
m_changing = false;
|
||||
return true;
|
||||
}
|
||||
return SignallingCircuit::setParams(params);
|
||||
}
|
||||
|
||||
bool MGCPCircuit::getParams(NamedList& params, const String& category)
|
||||
{
|
||||
if (category != "rtp")
|
||||
return false;
|
||||
waitNotChanging();
|
||||
addRtpParams(params,String::empty(),0,true);
|
||||
m_changing = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1358,6 +1521,10 @@ bool MGCPCircuit::sendEvent(SignallingCircuitEvent::Type type, NamedList* params
|
|||
DDebug(&splugin,DebugAll,"MGCPCircuit::sendEvent(%u,%p) %u [%p]",
|
||||
type,params,code(),this);
|
||||
switch (type) {
|
||||
case SignallingCircuitEvent::Connect:
|
||||
if (params)
|
||||
setParams(*params);
|
||||
return status(Connected,!params || params->getBoolValue("sync",true));
|
||||
case SignallingCircuitEvent::RingBegin:
|
||||
return fxs() && sendRequest("L/rg");
|
||||
// case SignallingCircuitEvent::RingEnd:
|
||||
|
@ -1434,6 +1601,11 @@ bool MGCPCircuit::processNotify(const String& package, const String& event, cons
|
|||
return enqueueEvent(SignallingCircuitEvent::Polarity,fullName);
|
||||
}
|
||||
else if (package == "D") {
|
||||
#if 0
|
||||
// TEST
|
||||
Debug(&splugin,DebugStub,"MGCPCircuit::processNotify() sending DTMF req [%p]",this);
|
||||
sendRequest(0,"D/[0-9#*](N)");
|
||||
#endif
|
||||
// DTMF events
|
||||
if (event.length() == 1)
|
||||
return enqueueEvent(SignallingCircuitEvent::Dtmf,fullName,event);
|
||||
|
@ -1444,14 +1616,15 @@ bool MGCPCircuit::processNotify(const String& package, const String& event, cons
|
|||
// We were forcibly disconnected by the gateway
|
||||
void MGCPCircuit::processDelete(MGCPMessage* mm, const String& error)
|
||||
{
|
||||
waitNotChanging();
|
||||
if (m_connId)
|
||||
Debug(&splugin,DebugWarn,"Gateway deleted connection '%s' on circuit %u [%p]",
|
||||
m_connId.c_str(),code(),this);
|
||||
m_connId.clear();
|
||||
m_remoteIp.clear();
|
||||
m_remotePort = 0;
|
||||
m_sdpSession = 0;
|
||||
m_payloads = s_payloads;
|
||||
m_gwFormat.clear();
|
||||
m_gwFormatChanged = false;
|
||||
cleanupRtp();
|
||||
m_changing = false;
|
||||
unsigned int code = 0;
|
||||
String tmp(error);
|
||||
tmp >> code;
|
||||
|
@ -1469,7 +1642,8 @@ void MGCPCircuit::processDelete(MGCPMessage* mm, const String& error)
|
|||
}
|
||||
|
||||
// Enqueue an event detected by this circuit
|
||||
bool MGCPCircuit::enqueueEvent(SignallingCircuitEvent::Type type, const char* name, const char* dtmf)
|
||||
bool MGCPCircuit::enqueueEvent(SignallingCircuitEvent::Type type, const char* name,
|
||||
const char* dtmf)
|
||||
{
|
||||
DDebug(&splugin,DebugAll,"Enqueueing event %u '%s' '%s' on %u [%p]",
|
||||
type,name,dtmf,code(),this);
|
||||
|
@ -1553,9 +1727,11 @@ bool DTMFHandler::received(Message& msg)
|
|||
|
||||
|
||||
MGCPPlugin::MGCPPlugin()
|
||||
: Module("mgcpca","misc")
|
||||
: Module("mgcpca","misc"),
|
||||
m_parser("mgcpca","PSTN Circuit")
|
||||
{
|
||||
Output("Loaded module MGCP-CA");
|
||||
m_parser.debugChain(this);
|
||||
}
|
||||
|
||||
MGCPPlugin::~MGCPPlugin()
|
||||
|
@ -1644,6 +1820,7 @@ void MGCPPlugin::initialize()
|
|||
Engine::install(new DTMFHandler);
|
||||
}
|
||||
}
|
||||
m_parser.initialize(cfg.getSection("codecs"),cfg.getSection("hacks"));
|
||||
}
|
||||
|
||||
}; // anonymous namespace
|
||||
|
|
|
@ -94,6 +94,11 @@ private:
|
|||
void evAnswer(SignallingEvent* event);
|
||||
void evRinging(SignallingEvent* event);
|
||||
void evCircuit(SignallingEvent* event);
|
||||
// Handle RTP forward from a message.
|
||||
// Return a circuit event to be sent or 0 if not handled
|
||||
SignallingCircuitEvent* handleRtp(Message& msg);
|
||||
// Set RTP data from circuit to message
|
||||
bool addRtp(Message& msg, bool possible = false);
|
||||
// Update circuit and format in source, optionally in consumer too
|
||||
void updateCircuitFormat(SignallingEvent* event, bool consumer);
|
||||
// Open or update format source/consumer
|
||||
|
@ -115,6 +120,8 @@ private:
|
|||
bool m_hungup; // Hang up flag
|
||||
String m_reason; // Hangup reason
|
||||
bool m_inband; // True to try to send in-band tones
|
||||
bool m_rtpForward; // Forward RTP
|
||||
bool m_sdpForward; // Forward SDP (only of rtp forward is enabled)
|
||||
Message* m_route; // Prepared call.preroute message
|
||||
};
|
||||
|
||||
|
@ -642,6 +649,8 @@ SigChannel::SigChannel(SignallingEvent* event)
|
|||
m_trunk(0),
|
||||
m_hungup(true),
|
||||
m_inband(false),
|
||||
m_rtpForward(false),
|
||||
m_sdpForward(false),
|
||||
m_route(0)
|
||||
{
|
||||
if (!(m_call && m_call->ref())) {
|
||||
|
@ -660,8 +669,12 @@ SigChannel::SigChannel(SignallingEvent* event)
|
|||
m_hungup = false;
|
||||
setState(0);
|
||||
SignallingCircuit* cic = getCircuit();
|
||||
if (m_trunk && cic)
|
||||
m_address << m_trunk->name() << "/" << cic->code();
|
||||
if (cic) {
|
||||
if (m_trunk)
|
||||
m_address << m_trunk->name() << "/" << cic->code();
|
||||
m_rtpForward = cic->getBoolParam("rtp_forward");
|
||||
m_sdpForward = cic->getBoolParam("sdp_forward");
|
||||
}
|
||||
Message* m = message("chan.startup");
|
||||
m->setParam("direction",status());
|
||||
m->addParam("caller",m_caller);
|
||||
|
@ -689,6 +702,8 @@ SigChannel::SigChannel(const char* caller, const char* called)
|
|||
m_hungup(true),
|
||||
m_reason("noconn"),
|
||||
m_inband(false),
|
||||
m_rtpForward(false),
|
||||
m_sdpForward(false),
|
||||
m_route(0)
|
||||
{
|
||||
}
|
||||
|
@ -704,6 +719,15 @@ bool SigChannel::startRouter()
|
|||
{
|
||||
Message* m = m_route;
|
||||
m_route = 0;
|
||||
Lock lock(m_mutex);
|
||||
SignallingCircuit* cic = getCircuit();
|
||||
String addr;
|
||||
if (cic && cic->getParam("rtp_addr",addr)) {
|
||||
m_rtpForward = true;
|
||||
m_sdpForward = cic->getBoolParam("sdp_forward");
|
||||
addRtp(*m,true);
|
||||
}
|
||||
lock.drop();
|
||||
return Channel::startRouter(m);
|
||||
}
|
||||
|
||||
|
@ -748,6 +772,11 @@ bool SigChannel::startCall(Message& msg, String& trunks)
|
|||
else
|
||||
cic->setParam("echocancel",String::boolText(echo->toBoolean(true)));
|
||||
}
|
||||
m_rtpForward = cic->getBoolParam("rtp_forward") && msg.getBoolValue("rtp_forward");
|
||||
if (m_rtpForward) {
|
||||
m_sdpForward = (0 != msg.getParam("sdp_raw"));
|
||||
msg.setParam("rtp_forward","accepted");
|
||||
}
|
||||
}
|
||||
setMaxcall(msg);
|
||||
Message* m = message("chan.startup",msg);
|
||||
|
@ -781,6 +810,12 @@ bool SigChannel::startCall(Message& msg, SigTrunk* trunk)
|
|||
sigMsg->params().copyParam(msg,"callednumtype");
|
||||
sigMsg->params().copyParam(msg,"callednumplan");
|
||||
sigMsg->params().copyParam(msg,"calledpointcode");
|
||||
// Copy RTP parameters
|
||||
if (msg.getBoolValue("rtp_forward")) {
|
||||
NamedList* tmp = new NamedList("rtp");
|
||||
tmp->copyParams(msg);
|
||||
sigMsg->params().addParam(new NamedPointer("circuit_parameters",tmp));
|
||||
}
|
||||
// Copy routing params
|
||||
unsigned int n = msg.length();
|
||||
String prefix;
|
||||
|
@ -838,7 +873,10 @@ bool SigChannel::msgProgress(Message& msg)
|
|||
}
|
||||
SignallingEvent* event = new SignallingEvent(SignallingEvent::Progress,sm,m_call);
|
||||
TelEngine::destruct(sm);
|
||||
SignallingCircuitEvent* cicEvent = handleRtp(msg);
|
||||
lock.drop();
|
||||
if (cicEvent)
|
||||
cicEvent->sendEvent();
|
||||
plugin.copySigMsgParams(event,msg);
|
||||
event->sendEvent();
|
||||
return true;
|
||||
|
@ -859,7 +897,10 @@ bool SigChannel::msgRinging(Message& msg)
|
|||
}
|
||||
SignallingEvent* event = new SignallingEvent(SignallingEvent::Ringing,sm,m_call);
|
||||
TelEngine::destruct(sm);
|
||||
SignallingCircuitEvent* cicEvent = handleRtp(msg);
|
||||
lock.drop();
|
||||
if (cicEvent)
|
||||
cicEvent->sendEvent();
|
||||
plugin.copySigMsgParams(event,msg);
|
||||
event->sendEvent();
|
||||
return true;
|
||||
|
@ -886,7 +927,10 @@ bool SigChannel::msgAnswered(Message& msg)
|
|||
}
|
||||
SignallingEvent* event = new SignallingEvent(SignallingEvent::Answer,sm,m_call);
|
||||
TelEngine::destruct(sm);
|
||||
SignallingCircuitEvent* cicEvent = handleRtp(msg);
|
||||
lock.drop();
|
||||
if (cicEvent)
|
||||
cicEvent->sendEvent();
|
||||
plugin.copySigMsgParams(event,msg);
|
||||
event->sendEvent();
|
||||
return true;
|
||||
|
@ -964,6 +1008,8 @@ bool SigChannel::callPrerouted(Message& msg, bool handled)
|
|||
bool SigChannel::callRouted(Message& msg)
|
||||
{
|
||||
Lock lock(m_mutex);
|
||||
if (m_rtpForward && !msg.getBoolValue("rtp_forward"))
|
||||
m_rtpForward = false;
|
||||
setState("routed",false);
|
||||
return m_call != 0;
|
||||
}
|
||||
|
@ -983,6 +1029,11 @@ void SigChannel::callAccept(Message& msg)
|
|||
event = new SignallingEvent(SignallingEvent::Accept,sm,m_call);
|
||||
TelEngine::destruct(sm);
|
||||
}
|
||||
if (m_rtpForward) {
|
||||
const String* tmp = msg.getParam("rtp_forward");
|
||||
if (!(tmp && (*tmp == "accepted")))
|
||||
m_rtpForward = false;
|
||||
}
|
||||
setState("accepted",false);
|
||||
lock.drop();
|
||||
if (event) {
|
||||
|
@ -1098,6 +1149,7 @@ void SigChannel::evProgress(SignallingEvent* event)
|
|||
updateCircuitFormat(event,false);
|
||||
Message* msg = message("call.progress");
|
||||
plugin.copySigMsgParams(*msg,event,&s_noPrefixParams);
|
||||
addRtp(*msg);
|
||||
Engine::enqueue(msg);
|
||||
}
|
||||
|
||||
|
@ -1129,6 +1181,7 @@ void SigChannel::evAnswer(SignallingEvent* event)
|
|||
Message* msg = message("call.answered",false,true);
|
||||
plugin.copySigMsgParams(*msg,event,&s_noPrefixParams);
|
||||
msg->clearParam("earlymedia");
|
||||
addRtp(*msg);
|
||||
Engine::enqueue(msg);
|
||||
}
|
||||
|
||||
|
@ -1138,6 +1191,7 @@ void SigChannel::evRinging(SignallingEvent* event)
|
|||
updateCircuitFormat(event,false);
|
||||
Message* msg = message("call.ringing",false,true);
|
||||
plugin.copySigMsgParams(*msg,event,&s_noPrefixParams);
|
||||
addRtp(*msg);
|
||||
Engine::enqueue(msg);
|
||||
}
|
||||
|
||||
|
@ -1157,6 +1211,42 @@ void SigChannel::evCircuit(SignallingEvent* event)
|
|||
}
|
||||
}
|
||||
|
||||
// Handle RTP forward from a message.
|
||||
// Return a circuit event to be sent or 0 if not handled
|
||||
SignallingCircuitEvent* SigChannel::handleRtp(Message& msg)
|
||||
{
|
||||
if (!(m_rtpForward && msg.getBoolValue("rtp_forward")))
|
||||
return 0;
|
||||
SignallingCircuit* cic = getCircuit();
|
||||
if (!cic)
|
||||
return 0;
|
||||
SignallingCircuitEvent* ev = new SignallingCircuitEvent(cic,
|
||||
SignallingCircuitEvent::Connect,"rtp");
|
||||
ev->copyParams(msg);
|
||||
return ev;
|
||||
}
|
||||
|
||||
// Set RTP data from circuit to message
|
||||
bool SigChannel::addRtp(Message& msg, bool possible)
|
||||
{
|
||||
if (!m_rtpForward)
|
||||
return false;
|
||||
SignallingCircuit* cic = getCircuit();
|
||||
if (!cic)
|
||||
return false;
|
||||
bool ok = cic->getParams(msg,"rtp");
|
||||
if (m_sdpForward) {
|
||||
String sdp;
|
||||
if (cic->getParam("sdp_raw",sdp) && sdp) {
|
||||
ok = true;
|
||||
msg.setParam("sdp_raw",sdp);
|
||||
}
|
||||
}
|
||||
if (ok)
|
||||
msg.setParam("rtp_forward",possible ? "possible" : String::boolText(true));
|
||||
return ok;
|
||||
}
|
||||
|
||||
void SigChannel::updateCircuitFormat(SignallingEvent* event, bool consumer)
|
||||
{
|
||||
const char* format = 0;
|
||||
|
@ -1173,6 +1263,8 @@ void SigChannel::updateCircuitFormat(SignallingEvent* event, bool consumer)
|
|||
|
||||
bool SigChannel::updateConsumer(const char* format, bool force)
|
||||
{
|
||||
if (m_rtpForward)
|
||||
return true;
|
||||
DataConsumer* consumer = getConsumer();
|
||||
SignallingCircuit* cic = getCircuit();
|
||||
if (!cic)
|
||||
|
@ -1194,6 +1286,8 @@ bool SigChannel::updateConsumer(const char* format, bool force)
|
|||
|
||||
bool SigChannel::updateSource(const char* format, bool force)
|
||||
{
|
||||
if (m_rtpForward)
|
||||
return true;
|
||||
DataSource* source = getSource();
|
||||
SignallingCircuit* cic = getCircuit();
|
||||
if (!cic)
|
||||
|
|
1219
modules/ysipchan.cpp
1219
modules/ysipchan.cpp
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue