Added capability to force a ringback to a MGCP gateway from ISDN and ISUP.
Fixed ring end on FXS analog MGCP gateways. git-svn-id: http://voip.null.ro/svn/yate@4062 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
26f88f5539
commit
13a1cf786d
|
@ -146,6 +146,10 @@
|
||||||
; alaw is used commonly in Europe while mulaw is used commonly in US and Japan.
|
; alaw is used commonly in Europe while mulaw is used commonly in US and Japan.
|
||||||
;format=alaw
|
;format=alaw
|
||||||
|
|
||||||
|
; ringback: boolean: Offer a ringback tone even if not provided by peer channel
|
||||||
|
; If it fails the correct indication (no inband available) is signaled
|
||||||
|
;ringback=no
|
||||||
|
|
||||||
; print-messages: boolean: Print decoded protocol data units to output
|
; print-messages: boolean: Print decoded protocol data units to output
|
||||||
; This option is applied on reload
|
; This option is applied on reload
|
||||||
; Defaults to no
|
; Defaults to no
|
||||||
|
@ -377,6 +381,10 @@
|
||||||
; If not set calls that request continuity check will be rejected
|
; If not set calls that request continuity check will be rejected
|
||||||
;continuity=
|
;continuity=
|
||||||
|
|
||||||
|
; ringback: boolean: Offer a ringback tone even if not provided by peer channel
|
||||||
|
; If it fails the correct indication (no inband available) is signaled
|
||||||
|
;ringback=no
|
||||||
|
|
||||||
; location: string: Exchange location to be set when sending Q.850 causes
|
; location: string: Exchange location to be set when sending Q.850 causes
|
||||||
; Available values are:
|
; Available values are:
|
||||||
; U User
|
; U User
|
||||||
|
|
|
@ -1466,6 +1466,7 @@ public:
|
||||||
enum Type {
|
enum Type {
|
||||||
Unknown = 0,
|
Unknown = 0,
|
||||||
Dtmf = 1, // Transfer tones: param: tone
|
Dtmf = 1, // Transfer tones: param: tone
|
||||||
|
GenericTone = 2, // Play or detect tones: param: tone
|
||||||
// Analog line events
|
// Analog line events
|
||||||
Timeout = 10, //
|
Timeout = 10, //
|
||||||
Polarity = 11, // Line's polarity changed
|
Polarity = 11, // Line's polarity changed
|
||||||
|
|
|
@ -227,6 +227,7 @@ private:
|
||||||
bool sendAsync(MGCPMessage* mm);
|
bool sendAsync(MGCPMessage* mm);
|
||||||
RefPointer<MGCPMessage> sendSync(MGCPMessage* mm);
|
RefPointer<MGCPMessage> sendSync(MGCPMessage* mm);
|
||||||
bool sendRequest(const char* sigReq, const char* reqEvt = 0, const char* digitMap = 0);
|
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);
|
bool enqueueEvent(SignallingCircuitEvent::Type type, const char* name, const char* dtmf = 0);
|
||||||
void cleanupRtp();
|
void cleanupRtp();
|
||||||
bool createRtp();
|
bool createRtp();
|
||||||
|
@ -236,6 +237,7 @@ private:
|
||||||
String m_notify;
|
String m_notify;
|
||||||
String m_specialMode;
|
String m_specialMode;
|
||||||
bool m_changing;
|
bool m_changing;
|
||||||
|
bool m_pending;
|
||||||
// Gateway endpoint bearer information
|
// Gateway endpoint bearer information
|
||||||
String m_gwFormat;
|
String m_gwFormat;
|
||||||
bool m_gwFormatChanged;
|
bool m_gwFormatChanged;
|
||||||
|
@ -1214,7 +1216,8 @@ bool MGCPSpan::processDelete(MGCPTransaction* tr, MGCPMessage* mm, const String&
|
||||||
MGCPCircuit::MGCPCircuit(unsigned int code, MGCPSpan* span, const char* id)
|
MGCPCircuit::MGCPCircuit(unsigned int code, MGCPSpan* span, const char* id)
|
||||||
: SignallingCircuit(RTP,code,Missing,span->group(),span),
|
: SignallingCircuit(RTP,code,Missing,span->group(),span),
|
||||||
SDPSession(&splugin.parser()),
|
SDPSession(&splugin.parser()),
|
||||||
m_epId(id), m_statusReq(Missing), m_changing(false), m_gwFormatChanged(false),
|
m_epId(id), m_statusReq(Missing),
|
||||||
|
m_changing(false), m_pending(false), m_gwFormatChanged(false),
|
||||||
m_localRtpChanged(false), m_needClear(false), m_tr(0)
|
m_localRtpChanged(false), m_needClear(false), m_tr(0)
|
||||||
{
|
{
|
||||||
Debug(&splugin,DebugAll,"MGCPCircuit::MGCPCircuit(%u,%p,'%s') [%p]",
|
Debug(&splugin,DebugAll,"MGCPCircuit::MGCPCircuit(%u,%p,'%s') [%p]",
|
||||||
|
@ -1360,6 +1363,7 @@ void MGCPCircuit::clearConn(bool force)
|
||||||
m_remoteRawSdp.clear();
|
m_remoteRawSdp.clear();
|
||||||
m_localRtpChanged = false;
|
m_localRtpChanged = false;
|
||||||
sendAsync(mm);
|
sendAsync(mm);
|
||||||
|
sendPending();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for changing flag to be false
|
// Wait for changing flag to be false
|
||||||
|
@ -1438,6 +1442,8 @@ bool MGCPCircuit::sendRequest(const char* sigReq, const char* reqEvt, const char
|
||||||
mm->params.addParam("X",m_notify);
|
mm->params.addParam("X",m_notify);
|
||||||
if (sigReq)
|
if (sigReq)
|
||||||
mm->params.addParam("S",sigReq);
|
mm->params.addParam("S",sigReq);
|
||||||
|
else
|
||||||
|
m_pending = false;
|
||||||
if (reqEvt)
|
if (reqEvt)
|
||||||
mm->params.addParam("R",reqEvt);
|
mm->params.addParam("R",reqEvt);
|
||||||
if (digitMap)
|
if (digitMap)
|
||||||
|
@ -1445,6 +1451,25 @@ bool MGCPCircuit::sendRequest(const char* sigReq, const char* reqEvt, const char
|
||||||
return sendAsync(mm);
|
return sendAsync(mm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send or clear pending (timeout) signal requests
|
||||||
|
bool MGCPCircuit::sendPending(const char* sigReq)
|
||||||
|
{
|
||||||
|
if (TelEngine::null(sigReq) && !m_pending)
|
||||||
|
return true;
|
||||||
|
Debug(&splugin,DebugInfo,"MGCPCircuit %s pending%s%s %u [%p]",
|
||||||
|
(sigReq ? "Signal" : "Clear all"),
|
||||||
|
(sigReq ? ": " : ""),c_safe(sigReq),
|
||||||
|
code(),this);
|
||||||
|
MGCPMessage* mm = message("RQNT");
|
||||||
|
mm->params.addParam("X",m_notify);
|
||||||
|
if (sigReq)
|
||||||
|
mm->params.addParam("S",sigReq);
|
||||||
|
if (!sendAsync(mm))
|
||||||
|
return false;
|
||||||
|
m_pending = !TelEngine::null(sigReq);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Circuit status change request
|
// Circuit status change request
|
||||||
bool MGCPCircuit::status(Status newStat, bool sync)
|
bool MGCPCircuit::status(Status newStat, bool sync)
|
||||||
{
|
{
|
||||||
|
@ -1657,11 +1682,12 @@ bool MGCPCircuit::sendEvent(SignallingCircuitEvent::Type type, NamedList* params
|
||||||
case SignallingCircuitEvent::Connect:
|
case SignallingCircuitEvent::Connect:
|
||||||
if (params)
|
if (params)
|
||||||
setParams(*params);
|
setParams(*params);
|
||||||
|
sendPending();
|
||||||
return status(Connected,!params || params->getBoolValue("sync",true));
|
return status(Connected,!params || params->getBoolValue("sync",true));
|
||||||
case SignallingCircuitEvent::RingBegin:
|
case SignallingCircuitEvent::RingBegin:
|
||||||
return fxs() && sendRequest("L/rg");
|
return fxs() && sendPending("L/rg");
|
||||||
// case SignallingCircuitEvent::RingEnd:
|
case SignallingCircuitEvent::RingEnd:
|
||||||
// return fxs() && sendRequest("L/rg(-)");
|
return fxs() && sendPending();
|
||||||
case SignallingCircuitEvent::Polarity:
|
case SignallingCircuitEvent::Polarity:
|
||||||
return fxs() && sendRequest("L/lsa");
|
return fxs() && sendRequest("L/lsa");
|
||||||
case SignallingCircuitEvent::OffHook:
|
case SignallingCircuitEvent::OffHook:
|
||||||
|
@ -1679,6 +1705,19 @@ bool MGCPCircuit::sendEvent(SignallingCircuitEvent::Type type, NamedList* params
|
||||||
return sendRequest("D/" + *tone);
|
return sendRequest("D/" + *tone);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case SignallingCircuitEvent::GenericTone:
|
||||||
|
if (params) {
|
||||||
|
const String* tone = params->getParam("tone");
|
||||||
|
if (!tone)
|
||||||
|
tone = params;
|
||||||
|
if (null(tone))
|
||||||
|
break;
|
||||||
|
if (*tone == "ringback" || *tone == "ring" || *tone == "rt")
|
||||||
|
return sendPending("G/rt");
|
||||||
|
if (*tone == "congestion" || *tone == "cg")
|
||||||
|
return sendPending("G/cg");
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,6 +136,7 @@ private:
|
||||||
bool m_hungup; // Hang up flag
|
bool m_hungup; // Hang up flag
|
||||||
String m_reason; // Hangup reason
|
String m_reason; // Hangup reason
|
||||||
bool m_inband; // True to try to send in-band tones
|
bool m_inband; // True to try to send in-band tones
|
||||||
|
bool m_ringback; // Always provide ringback media
|
||||||
bool m_rtpForward; // Forward RTP
|
bool m_rtpForward; // Forward RTP
|
||||||
bool m_sdpForward; // Forward SDP (only of rtp forward is enabled)
|
bool m_sdpForward; // Forward SDP (only of rtp forward is enabled)
|
||||||
Message* m_route; // Prepared call.preroute message
|
Message* m_route; // Prepared call.preroute message
|
||||||
|
@ -329,6 +330,8 @@ public:
|
||||||
{ return m_controller; }
|
{ return m_controller; }
|
||||||
inline bool inband() const
|
inline bool inband() const
|
||||||
{ return m_inband; }
|
{ return m_inband; }
|
||||||
|
inline bool ringback() const
|
||||||
|
{ return m_ringback; }
|
||||||
// Set exiting flag for call controller and timeout for the thread
|
// Set exiting flag for call controller and timeout for the thread
|
||||||
void setExiting(unsigned int msec);
|
void setExiting(unsigned int msec);
|
||||||
// Initialize (create or reload) the trunk. Process the debuglayer parameter.
|
// Initialize (create or reload) the trunk. Process the debuglayer parameter.
|
||||||
|
@ -376,6 +379,7 @@ protected:
|
||||||
SignallingCallControl* m_controller; // Call controller, if any
|
SignallingCallControl* m_controller; // Call controller, if any
|
||||||
bool m_init; // True if already initialized
|
bool m_init; // True if already initialized
|
||||||
bool m_inband; // True to send in-band tones through this trunk
|
bool m_inband; // True to send in-band tones through this trunk
|
||||||
|
bool m_ringback; // Always provide ringback media
|
||||||
private:
|
private:
|
||||||
Type m_type; // Trunk type
|
Type m_type; // Trunk type
|
||||||
SigTrunkThread* m_thread; // Event thread for call controller
|
SigTrunkThread* m_thread; // Event thread for call controller
|
||||||
|
@ -792,6 +796,7 @@ SigChannel::SigChannel(SignallingEvent* event)
|
||||||
m_trunk(0),
|
m_trunk(0),
|
||||||
m_hungup(true),
|
m_hungup(true),
|
||||||
m_inband(false),
|
m_inband(false),
|
||||||
|
m_ringback(false),
|
||||||
m_rtpForward(false),
|
m_rtpForward(false),
|
||||||
m_sdpForward(false),
|
m_sdpForward(false),
|
||||||
m_route(0),
|
m_route(0),
|
||||||
|
@ -807,8 +812,10 @@ SigChannel::SigChannel(SignallingEvent* event)
|
||||||
m_called = msg ? msg->params().getValue("called") : 0;
|
m_called = msg ? msg->params().getValue("called") : 0;
|
||||||
m_call->userdata(this);
|
m_call->userdata(this);
|
||||||
m_trunk = plugin.findTrunk(m_call->controller());
|
m_trunk = plugin.findTrunk(m_call->controller());
|
||||||
if (m_trunk)
|
if (m_trunk) {
|
||||||
m_inband = m_trunk->inband();
|
m_inband = m_trunk->inband();
|
||||||
|
m_ringback = m_trunk->ringback();
|
||||||
|
}
|
||||||
// Startup
|
// Startup
|
||||||
m_hungup = false;
|
m_hungup = false;
|
||||||
setState(0);
|
setState(0);
|
||||||
|
@ -851,6 +858,7 @@ SigChannel::SigChannel(const char* caller, const char* called)
|
||||||
m_hungup(true),
|
m_hungup(true),
|
||||||
m_reason("noconn"),
|
m_reason("noconn"),
|
||||||
m_inband(false),
|
m_inband(false),
|
||||||
|
m_ringback(false),
|
||||||
m_rtpForward(false),
|
m_rtpForward(false),
|
||||||
m_sdpForward(false),
|
m_sdpForward(false),
|
||||||
m_route(0),
|
m_route(0),
|
||||||
|
@ -951,6 +959,7 @@ bool SigChannel::startCall(Message& msg, SigTrunk* trunk)
|
||||||
return false;
|
return false;
|
||||||
// Data
|
// Data
|
||||||
m_inband = msg.getBoolValue("dtmfinband",trunk->inband());
|
m_inband = msg.getBoolValue("dtmfinband",trunk->inband());
|
||||||
|
m_ringback = msg.getBoolValue("ringback",trunk->ringback());
|
||||||
// Make the call
|
// Make the call
|
||||||
SignallingMessage* sigMsg = new SignallingMessage;
|
SignallingMessage* sigMsg = new SignallingMessage;
|
||||||
sigMsg->params().addParam("caller",m_caller);
|
sigMsg->params().addParam("caller",m_caller);
|
||||||
|
@ -1037,6 +1046,8 @@ bool SigChannel::msgProgress(Message& msg)
|
||||||
SignallingMessage* sm = new SignallingMessage;
|
SignallingMessage* sm = new SignallingMessage;
|
||||||
if (media && updateConsumer(format,false) && format)
|
if (media && updateConsumer(format,false) && format)
|
||||||
sm->params().addParam("format",format);
|
sm->params().addParam("format",format);
|
||||||
|
if (media)
|
||||||
|
m_ringback = false;
|
||||||
sm->params().addParam("earlymedia",String::boolText(media));
|
sm->params().addParam("earlymedia",String::boolText(media));
|
||||||
SignallingEvent* event = new SignallingEvent(SignallingEvent::Progress,sm,m_call);
|
SignallingEvent* event = new SignallingEvent(SignallingEvent::Progress,sm,m_call);
|
||||||
TelEngine::destruct(sm);
|
TelEngine::destruct(sm);
|
||||||
|
@ -1060,6 +1071,17 @@ bool SigChannel::msgRinging(Message& msg)
|
||||||
SignallingMessage* sm = new SignallingMessage;
|
SignallingMessage* sm = new SignallingMessage;
|
||||||
if (media && updateConsumer(format,false) && format)
|
if (media && updateConsumer(format,false) && format)
|
||||||
sm->params().addParam("format",format);
|
sm->params().addParam("format",format);
|
||||||
|
if (m_ringback && !media) {
|
||||||
|
// Attempt to provide ringback using circuit features
|
||||||
|
SignallingCircuit* cic = getCircuit();
|
||||||
|
if (cic) {
|
||||||
|
NamedList params("ringback");
|
||||||
|
params.addParam("tone","ringback");
|
||||||
|
media = cic->sendEvent(SignallingCircuitEvent::GenericTone,¶ms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (media)
|
||||||
|
m_ringback = false;
|
||||||
sm->params().addParam("earlymedia",String::boolText(media));
|
sm->params().addParam("earlymedia",String::boolText(media));
|
||||||
SignallingEvent* event = new SignallingEvent(SignallingEvent::Ringing,sm,m_call);
|
SignallingEvent* event = new SignallingEvent(SignallingEvent::Ringing,sm,m_call);
|
||||||
TelEngine::destruct(sm);
|
TelEngine::destruct(sm);
|
||||||
|
@ -1078,6 +1100,7 @@ bool SigChannel::msgAnswered(Message& msg)
|
||||||
setState("answered");
|
setState("answered");
|
||||||
if (!m_call)
|
if (!m_call)
|
||||||
return true;
|
return true;
|
||||||
|
m_ringback = false;
|
||||||
updateSource(0,false);
|
updateSource(0,false);
|
||||||
// Start echo training
|
// Start echo training
|
||||||
SignallingCircuit* cic = getCircuit();
|
SignallingCircuit* cic = getCircuit();
|
||||||
|
@ -1222,6 +1245,7 @@ void SigChannel::callAccept(Message& msg)
|
||||||
}
|
}
|
||||||
TelEngine::destruct(sm);
|
TelEngine::destruct(sm);
|
||||||
}
|
}
|
||||||
|
m_ringback = msg.getBoolValue("ringback",m_ringback);
|
||||||
if (m_rtpForward) {
|
if (m_rtpForward) {
|
||||||
const String* tmp = msg.getParam("rtp_forward");
|
const String* tmp = msg.getParam("rtp_forward");
|
||||||
if (!(tmp && (*tmp == "accepted")))
|
if (!(tmp && (*tmp == "accepted")))
|
||||||
|
@ -2605,6 +2629,7 @@ SigTrunk::SigTrunk(const char* name, Type type)
|
||||||
m_controller(0),
|
m_controller(0),
|
||||||
m_init(false),
|
m_init(false),
|
||||||
m_inband(false),
|
m_inband(false),
|
||||||
|
m_ringback(false),
|
||||||
m_type(type),
|
m_type(type),
|
||||||
m_thread(0)
|
m_thread(0)
|
||||||
{
|
{
|
||||||
|
@ -2636,6 +2661,7 @@ bool SigTrunk::initialize(NamedList& params)
|
||||||
{
|
{
|
||||||
// Reload common parameters
|
// Reload common parameters
|
||||||
m_inband = params.getBoolValue("dtmfinband",s_cfg.getBoolValue("general","dtmfinband",false));
|
m_inband = params.getBoolValue("dtmfinband",s_cfg.getBoolValue("general","dtmfinband",false));
|
||||||
|
m_ringback = params.getBoolValue("ringback",s_cfg.getBoolValue("general","ringback",false));
|
||||||
|
|
||||||
// Check error:
|
// Check error:
|
||||||
// No need to initialize if no signalling engine or not in plugin's list
|
// No need to initialize if no signalling engine or not in plugin's list
|
||||||
|
|
Loading…
Reference in New Issue