Accept a comma separated list of links to try to send the call.
Detect early a congestion or network failure and attempt next link. git-svn-id: http://voip.null.ro/svn/yate@2368 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
96c30c706c
commit
501f0bef0e
|
@ -2142,8 +2142,9 @@ SignallingCall* SS7ISUP::call(SignallingMessage* msg, String& reason)
|
|||
reason = "noconn";
|
||||
return 0;
|
||||
}
|
||||
if (!m_l3LinkUp) {
|
||||
Debug(this,DebugNote,"L3 network is down");
|
||||
if (exiting() || !m_l3LinkUp) {
|
||||
Debug(this,DebugInfo,"Denying outgoing call request, reason: %s.",
|
||||
exiting() ? "exiting" : "L3 down");
|
||||
TelEngine::destruct(msg);
|
||||
reason = "net-out-of-order";
|
||||
return 0;
|
||||
|
@ -2157,6 +2158,7 @@ SignallingCall* SS7ISUP::call(SignallingMessage* msg, String& reason)
|
|||
SS7PointCode dest;
|
||||
SignallingCircuit* cic = 0;
|
||||
const char* range = msg->params().getValue("circuits");
|
||||
reason.clear();
|
||||
Lock lock(this);
|
||||
// Check
|
||||
while (true) {
|
||||
|
|
|
@ -720,6 +720,8 @@ ISDNQ931Call::ISDNQ931Call(ISDNQ931* controller, bool outgoing,
|
|||
q931()->setInterval(m_discTimer,305);
|
||||
q931()->setInterval(m_relTimer,308);
|
||||
q931()->setInterval(m_conTimer,313);
|
||||
if (outgoing)
|
||||
reserveCircuit();
|
||||
}
|
||||
|
||||
ISDNQ931Call::~ISDNQ931Call()
|
||||
|
@ -1571,7 +1573,7 @@ bool ISDNQ931Call::sendSetup(SignallingMessage* sigMsg)
|
|||
m_data.m_format = "alaw";
|
||||
m_data.processBearerCaps(msg,true);
|
||||
// ChannelID
|
||||
if (!reserveCircuit())
|
||||
if (!m_circuit)
|
||||
break;
|
||||
m_circuit->updateFormat(m_data.m_format,0);
|
||||
m_data.m_bri = false;
|
||||
|
@ -2532,6 +2534,11 @@ SignallingCall* ISDNQ931::call(SignallingMessage* msg, String& reason)
|
|||
return 0;
|
||||
}
|
||||
ISDNQ931Call* call = new ISDNQ931Call(this,true,m_callRef,m_callRefLen);
|
||||
if (!call->circuit()) {
|
||||
reason = "congestion";
|
||||
TelEngine::destruct(call);
|
||||
return 0;
|
||||
}
|
||||
call->ref();
|
||||
// Adjust m_callRef. Avoid to use 0
|
||||
m_callRef = (m_callRef + 1) & m_callRefMask;
|
||||
|
@ -2678,12 +2685,14 @@ void ISDNQ931::terminateCalls(ObjList* list, const char* reason)
|
|||
// Check if new calls are acceptable
|
||||
bool ISDNQ931::acceptNewCall(bool outgoing, String& reason)
|
||||
{
|
||||
if (!exiting())
|
||||
return true;
|
||||
Debug(this,DebugNote,"Denying %s call request. We are exiting",
|
||||
outgoing ? "outgoing" : "incoming");
|
||||
reason = "net-out-of-order";
|
||||
return false;
|
||||
if (exiting() || !m_q921 || !m_q921Up) {
|
||||
Debug(this,DebugInfo,"Denying %s call request, reason: %s.",
|
||||
outgoing ? "outgoing" : "incoming",
|
||||
exiting() ? "exiting" : "link down");
|
||||
reason = "net-out-of-order";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Helper function called in ISDNQ931::receive()
|
||||
|
|
|
@ -54,8 +54,9 @@ public:
|
|||
// Incoming
|
||||
SigChannel(SignallingEvent* event);
|
||||
// Outgoing
|
||||
SigChannel(Message& msg, const char* caller, const char* called, SigLink* link);
|
||||
SigChannel(const char* caller, const char* called);
|
||||
virtual ~SigChannel();
|
||||
bool startCall(Message& msg, String& links);
|
||||
inline SignallingCall* call() const
|
||||
{ return m_call; }
|
||||
inline SigLink* link() const
|
||||
|
@ -81,6 +82,7 @@ public:
|
|||
void handleEvent(SignallingEvent* event);
|
||||
void hangup(const char* reason = 0, SignallingEvent* event = 0);
|
||||
private:
|
||||
bool startCall(Message& msg, SigLink* link);
|
||||
virtual void statusParams(String& str);
|
||||
// Set call status. Print debug message
|
||||
void setState(const char* state, bool updateStatus = true, bool showReason = false);
|
||||
|
@ -516,7 +518,7 @@ SigChannel::SigChannel(SignallingEvent* event)
|
|||
: Channel(&plugin,0,false),
|
||||
m_call(event->call()),
|
||||
m_link(0),
|
||||
m_hungup(false),
|
||||
m_hungup(true),
|
||||
m_inband(false)
|
||||
{
|
||||
if (!(m_call && m_call->ref())) {
|
||||
|
@ -532,6 +534,7 @@ SigChannel::SigChannel(SignallingEvent* event)
|
|||
if (m_link)
|
||||
m_inband = m_link->inband();
|
||||
// Startup
|
||||
m_hungup = false;
|
||||
setState(0);
|
||||
SignallingCircuit* cic = getCircuit();
|
||||
if (m_link && cic)
|
||||
|
@ -546,27 +549,87 @@ SigChannel::SigChannel(SignallingEvent* event)
|
|||
Engine::enqueue(m);
|
||||
}
|
||||
|
||||
// Construct an outgoing channel
|
||||
SigChannel::SigChannel(Message& msg, const char* caller, const char* called, SigLink* link)
|
||||
// Construct an unstarted outgoing channel
|
||||
SigChannel::SigChannel(const char* caller, const char* called)
|
||||
: Channel(&plugin,0,true),
|
||||
m_caller(caller),
|
||||
m_called(called),
|
||||
m_call(0),
|
||||
m_link(link),
|
||||
m_hungup(false),
|
||||
m_link(0),
|
||||
m_hungup(true),
|
||||
m_reason("noconn"),
|
||||
m_inband(false)
|
||||
{
|
||||
if (!(m_link && m_link->controller())) {
|
||||
msg.setParam("error","noconn");
|
||||
m_hungup = true;
|
||||
return;
|
||||
}
|
||||
|
||||
SigChannel::~SigChannel()
|
||||
{
|
||||
hangup();
|
||||
setState("destroyed",true,true);
|
||||
}
|
||||
|
||||
// Start outgoing call by name of a link or list of links
|
||||
bool SigChannel::startCall(Message& msg, String& links)
|
||||
{
|
||||
ObjList* linkList = links.split(',',false);
|
||||
unsigned int n = linkList->length();
|
||||
for (unsigned int i = 0; i < n; i++) {
|
||||
const String* linkName = static_cast<const String*>((*linkList)[i]);
|
||||
if (!linkName)
|
||||
continue;
|
||||
SigLink* link = plugin.findLink(*linkName,true);
|
||||
if (link && startCall(msg,link)) {
|
||||
// success - update link parameter in message
|
||||
links = *linkName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete linkList;
|
||||
|
||||
setState(0);
|
||||
if (!m_call) {
|
||||
msg.setParam("error",m_reason);
|
||||
return false;
|
||||
}
|
||||
// Since the channel started the call remember to hang up as well
|
||||
m_hungup = false;
|
||||
SignallingCircuit* cic = getCircuit();
|
||||
if (cic) {
|
||||
m_address << m_link->name() << "/" << cic->code();
|
||||
// Set echo cancel
|
||||
const String* echo = msg.getParam("cancelecho");
|
||||
if (echo && *echo) {
|
||||
int taps = echo->toInteger(-1);
|
||||
if (taps > 0) {
|
||||
cic->setParam("echotaps",*echo);
|
||||
cic->setParam("echocancel",String::boolText(true));
|
||||
}
|
||||
else
|
||||
cic->setParam("echocancel",String::boolText(echo->toBoolean(true)));
|
||||
}
|
||||
}
|
||||
setMaxcall(msg);
|
||||
Message* m = message("chan.startup",msg);
|
||||
m->setParam("direction",status());
|
||||
m_targetid = msg.getValue("id");
|
||||
m->setParam("caller",m_caller);
|
||||
m->setParam("called",m_called);
|
||||
m->setParam("billid",msg.getValue("billid"));
|
||||
// TODO: Add call control parameter ?
|
||||
Engine::enqueue(m);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SigChannel::startCall(Message& msg, SigLink* link)
|
||||
{
|
||||
if (!(link && link->controller()))
|
||||
return false;
|
||||
// Data
|
||||
m_inband = msg.getBoolValue("dtmfinband",link->inband());
|
||||
// Make the call
|
||||
SignallingMessage* sigMsg = new SignallingMessage;
|
||||
sigMsg->params().addParam("caller",caller);
|
||||
sigMsg->params().addParam("called",called);
|
||||
sigMsg->params().addParam("caller",m_caller);
|
||||
sigMsg->params().addParam("called",m_called);
|
||||
sigMsg->params().addParam("callername",msg.getValue("callername"));
|
||||
sigMsg->params().copyParam(msg,"circuits");
|
||||
sigMsg->params().copyParam(msg,"format");
|
||||
|
@ -587,38 +650,15 @@ SigChannel::SigChannel(Message& msg, const char* caller, const char* called, Sig
|
|||
sigMsg->params().addParam(ns->name().substr(prefix.length()),*ns);
|
||||
}
|
||||
m_call = link->controller()->call(sigMsg,m_reason);
|
||||
setState(0);
|
||||
if (m_call) {
|
||||
m_call->userdata(this);
|
||||
SignallingCircuit* cic = getCircuit();
|
||||
if (cic) {
|
||||
m_address << m_link->name() << "/" << cic->code();
|
||||
// Set echo cancel
|
||||
const char* echo = msg.getValue("cancelecho");
|
||||
if (echo) {
|
||||
String value = echo;
|
||||
cic->setParam("echotaps",value);
|
||||
cic->setParam("echocancel",String::boolText(0 != value.toInteger()));
|
||||
}
|
||||
}
|
||||
setMaxcall(msg);
|
||||
m_link = link;
|
||||
m_reason.clear();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
msg.setParam("error",m_reason);
|
||||
Message* m = message("chan.startup",msg);
|
||||
m->setParam("direction",status());
|
||||
m_targetid = msg.getValue("id");
|
||||
m->setParam("caller",caller);
|
||||
m->setParam("called",called);
|
||||
m->setParam("billid",msg.getValue("billid"));
|
||||
// TODO: Add call control parameter ?
|
||||
Engine::enqueue(m);
|
||||
}
|
||||
|
||||
SigChannel::~SigChannel()
|
||||
{
|
||||
hangup();
|
||||
setState("destroyed",true,true);
|
||||
DDebug(this,DebugNote,"Failed to call on link '%s' reason: '%s' [%p]",
|
||||
link->name().safe(),m_reason.c_str(),this);
|
||||
return false;
|
||||
}
|
||||
|
||||
void SigChannel::handleEvent(SignallingEvent* event)
|
||||
|
@ -825,9 +865,9 @@ void SigChannel::hangup(const char* reason, SignallingEvent* event)
|
|||
Lock lock(m_mutex);
|
||||
if (m_hungup)
|
||||
return;
|
||||
m_hungup = true;
|
||||
setSource();
|
||||
setConsumer();
|
||||
m_hungup = true;
|
||||
if (m_reason.null())
|
||||
m_reason = reason ? reason : (Engine::exiting() ? "net-out-of-order" : "normal-clearing");
|
||||
setState("hangup",true,true);
|
||||
|
@ -1043,20 +1083,19 @@ bool SigDriver::msgExecute(Message& msg, String& dest)
|
|||
msg.setParam("error","failure");
|
||||
return false;
|
||||
}
|
||||
// Identify the call controller before create channel
|
||||
const char* tmp = msg.getValue("link");
|
||||
SigLink* link = findLink(tmp,true);
|
||||
if (!link) {
|
||||
// Locate and check the link parameter
|
||||
String* link = msg.getParam("link");
|
||||
if (!link || link->null()) {
|
||||
Debug(this,DebugNote,
|
||||
"Signalling call failed. No call controller named '%s'",tmp);
|
||||
msg.setParam("error","noroute");
|
||||
"Signalling call failed. No link specified");
|
||||
msg.setParam("error","noconn");
|
||||
return false;
|
||||
}
|
||||
// Create channel
|
||||
lock();
|
||||
SigChannel* sigCh = new SigChannel(msg,msg.getValue("caller"),dest,link);
|
||||
SigChannel* sigCh = new SigChannel(msg.getValue("caller"),dest);
|
||||
unlock();
|
||||
bool ok = sigCh->call() != 0;
|
||||
bool ok = sigCh->startCall(msg,*link);
|
||||
if (ok) {
|
||||
if (sigCh->connect(peer,msg.getValue("reason"))) {
|
||||
msg.setParam("peerid",sigCh->id());
|
||||
|
|
Loading…
Reference in New Issue