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.
|
||||
;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
|
||||
; This option is applied on reload
|
||||
; Defaults to no
|
||||
|
@ -377,6 +381,10 @@
|
|||
; If not set calls that request continuity check will be rejected
|
||||
;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
|
||||
; Available values are:
|
||||
; U User
|
||||
|
|
|
@ -1466,6 +1466,7 @@ public:
|
|||
enum Type {
|
||||
Unknown = 0,
|
||||
Dtmf = 1, // Transfer tones: param: tone
|
||||
GenericTone = 2, // Play or detect tones: param: tone
|
||||
// Analog line events
|
||||
Timeout = 10, //
|
||||
Polarity = 11, // Line's polarity changed
|
||||
|
|
|
@ -227,6 +227,7 @@ private:
|
|||
bool sendAsync(MGCPMessage* mm);
|
||||
RefPointer<MGCPMessage> sendSync(MGCPMessage* mm);
|
||||
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();
|
||||
bool createRtp();
|
||||
|
@ -236,6 +237,7 @@ private:
|
|||
String m_notify;
|
||||
String m_specialMode;
|
||||
bool m_changing;
|
||||
bool m_pending;
|
||||
// Gateway endpoint bearer information
|
||||
String m_gwFormat;
|
||||
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)
|
||||
: SignallingCircuit(RTP,code,Missing,span->group(),span),
|
||||
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)
|
||||
{
|
||||
Debug(&splugin,DebugAll,"MGCPCircuit::MGCPCircuit(%u,%p,'%s') [%p]",
|
||||
|
@ -1360,6 +1363,7 @@ void MGCPCircuit::clearConn(bool force)
|
|||
m_remoteRawSdp.clear();
|
||||
m_localRtpChanged = false;
|
||||
sendAsync(mm);
|
||||
sendPending();
|
||||
}
|
||||
|
||||
// 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);
|
||||
if (sigReq)
|
||||
mm->params.addParam("S",sigReq);
|
||||
else
|
||||
m_pending = false;
|
||||
if (reqEvt)
|
||||
mm->params.addParam("R",reqEvt);
|
||||
if (digitMap)
|
||||
|
@ -1445,6 +1451,25 @@ bool MGCPCircuit::sendRequest(const char* sigReq, const char* reqEvt, const char
|
|||
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
|
||||
bool MGCPCircuit::status(Status newStat, bool sync)
|
||||
{
|
||||
|
@ -1657,11 +1682,12 @@ bool MGCPCircuit::sendEvent(SignallingCircuitEvent::Type type, NamedList* params
|
|||
case SignallingCircuitEvent::Connect:
|
||||
if (params)
|
||||
setParams(*params);
|
||||
sendPending();
|
||||
return status(Connected,!params || params->getBoolValue("sync",true));
|
||||
case SignallingCircuitEvent::RingBegin:
|
||||
return fxs() && sendRequest("L/rg");
|
||||
// case SignallingCircuitEvent::RingEnd:
|
||||
// return fxs() && sendRequest("L/rg(-)");
|
||||
return fxs() && sendPending("L/rg");
|
||||
case SignallingCircuitEvent::RingEnd:
|
||||
return fxs() && sendPending();
|
||||
case SignallingCircuitEvent::Polarity:
|
||||
return fxs() && sendRequest("L/lsa");
|
||||
case SignallingCircuitEvent::OffHook:
|
||||
|
@ -1679,6 +1705,19 @@ bool MGCPCircuit::sendEvent(SignallingCircuitEvent::Type type, NamedList* params
|
|||
return sendRequest("D/" + *tone);
|
||||
}
|
||||
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:
|
||||
;
|
||||
}
|
||||
|
|
|
@ -136,6 +136,7 @@ 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_ringback; // Always provide ringback media
|
||||
bool m_rtpForward; // Forward RTP
|
||||
bool m_sdpForward; // Forward SDP (only of rtp forward is enabled)
|
||||
Message* m_route; // Prepared call.preroute message
|
||||
|
@ -329,6 +330,8 @@ public:
|
|||
{ return m_controller; }
|
||||
inline bool inband() const
|
||||
{ return m_inband; }
|
||||
inline bool ringback() const
|
||||
{ return m_ringback; }
|
||||
// Set exiting flag for call controller and timeout for the thread
|
||||
void setExiting(unsigned int msec);
|
||||
// Initialize (create or reload) the trunk. Process the debuglayer parameter.
|
||||
|
@ -376,6 +379,7 @@ protected:
|
|||
SignallingCallControl* m_controller; // Call controller, if any
|
||||
bool m_init; // True if already initialized
|
||||
bool m_inband; // True to send in-band tones through this trunk
|
||||
bool m_ringback; // Always provide ringback media
|
||||
private:
|
||||
Type m_type; // Trunk type
|
||||
SigTrunkThread* m_thread; // Event thread for call controller
|
||||
|
@ -792,6 +796,7 @@ SigChannel::SigChannel(SignallingEvent* event)
|
|||
m_trunk(0),
|
||||
m_hungup(true),
|
||||
m_inband(false),
|
||||
m_ringback(false),
|
||||
m_rtpForward(false),
|
||||
m_sdpForward(false),
|
||||
m_route(0),
|
||||
|
@ -807,8 +812,10 @@ SigChannel::SigChannel(SignallingEvent* event)
|
|||
m_called = msg ? msg->params().getValue("called") : 0;
|
||||
m_call->userdata(this);
|
||||
m_trunk = plugin.findTrunk(m_call->controller());
|
||||
if (m_trunk)
|
||||
if (m_trunk) {
|
||||
m_inband = m_trunk->inband();
|
||||
m_ringback = m_trunk->ringback();
|
||||
}
|
||||
// Startup
|
||||
m_hungup = false;
|
||||
setState(0);
|
||||
|
@ -851,6 +858,7 @@ SigChannel::SigChannel(const char* caller, const char* called)
|
|||
m_hungup(true),
|
||||
m_reason("noconn"),
|
||||
m_inband(false),
|
||||
m_ringback(false),
|
||||
m_rtpForward(false),
|
||||
m_sdpForward(false),
|
||||
m_route(0),
|
||||
|
@ -951,6 +959,7 @@ bool SigChannel::startCall(Message& msg, SigTrunk* trunk)
|
|||
return false;
|
||||
// Data
|
||||
m_inband = msg.getBoolValue("dtmfinband",trunk->inband());
|
||||
m_ringback = msg.getBoolValue("ringback",trunk->ringback());
|
||||
// Make the call
|
||||
SignallingMessage* sigMsg = new SignallingMessage;
|
||||
sigMsg->params().addParam("caller",m_caller);
|
||||
|
@ -1037,6 +1046,8 @@ bool SigChannel::msgProgress(Message& msg)
|
|||
SignallingMessage* sm = new SignallingMessage;
|
||||
if (media && updateConsumer(format,false) && format)
|
||||
sm->params().addParam("format",format);
|
||||
if (media)
|
||||
m_ringback = false;
|
||||
sm->params().addParam("earlymedia",String::boolText(media));
|
||||
SignallingEvent* event = new SignallingEvent(SignallingEvent::Progress,sm,m_call);
|
||||
TelEngine::destruct(sm);
|
||||
|
@ -1060,6 +1071,17 @@ bool SigChannel::msgRinging(Message& msg)
|
|||
SignallingMessage* sm = new SignallingMessage;
|
||||
if (media && updateConsumer(format,false) && 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));
|
||||
SignallingEvent* event = new SignallingEvent(SignallingEvent::Ringing,sm,m_call);
|
||||
TelEngine::destruct(sm);
|
||||
|
@ -1078,6 +1100,7 @@ bool SigChannel::msgAnswered(Message& msg)
|
|||
setState("answered");
|
||||
if (!m_call)
|
||||
return true;
|
||||
m_ringback = false;
|
||||
updateSource(0,false);
|
||||
// Start echo training
|
||||
SignallingCircuit* cic = getCircuit();
|
||||
|
@ -1222,6 +1245,7 @@ void SigChannel::callAccept(Message& msg)
|
|||
}
|
||||
TelEngine::destruct(sm);
|
||||
}
|
||||
m_ringback = msg.getBoolValue("ringback",m_ringback);
|
||||
if (m_rtpForward) {
|
||||
const String* tmp = msg.getParam("rtp_forward");
|
||||
if (!(tmp && (*tmp == "accepted")))
|
||||
|
@ -2605,6 +2629,7 @@ SigTrunk::SigTrunk(const char* name, Type type)
|
|||
m_controller(0),
|
||||
m_init(false),
|
||||
m_inband(false),
|
||||
m_ringback(false),
|
||||
m_type(type),
|
||||
m_thread(0)
|
||||
{
|
||||
|
@ -2636,6 +2661,7 @@ bool SigTrunk::initialize(NamedList& params)
|
|||
{
|
||||
// Reload common parameters
|
||||
m_inband = params.getBoolValue("dtmfinband",s_cfg.getBoolValue("general","dtmfinband",false));
|
||||
m_ringback = params.getBoolValue("ringback",s_cfg.getBoolValue("general","ringback",false));
|
||||
|
||||
// Check error:
|
||||
// No need to initialize if no signalling engine or not in plugin's list
|
||||
|
|
Loading…
Reference in New Issue