Added more circuit lock flags. Simplified code.
git-svn-id: http://yate.null.ro/svn/yate/trunk@1794 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
5a85434cc1
commit
298d4fe4fb
|
@ -2025,6 +2025,7 @@ SS7ISUP::SS7ISUP(const NamedList& params)
|
|||
else
|
||||
s << "missing";
|
||||
s << " priority+SSF=" << (unsigned int)m_priossf;
|
||||
s << " lockcircuits" << params.getValue("lockcircuits");
|
||||
Debug(this,DebugInfo,"ISUP Call Controller %s [%p]",s.c_str(),this);
|
||||
}
|
||||
}
|
||||
|
@ -2233,6 +2234,10 @@ void SS7ISUP::notify(SS7Layer3* link, int sls)
|
|||
return;
|
||||
DDebug(this,DebugInfo,"L3 (%p,'%s') is %soperational",link,
|
||||
link->toString().safe(),link->operational()?"":"not ");
|
||||
if (!link->operational(sls))
|
||||
return;
|
||||
Debug(this,DebugStub,"L3 (%p,'%s') is operational: please implement circuit block/unblock",
|
||||
link,link->toString().safe());
|
||||
}
|
||||
|
||||
SS7MSU* SS7ISUP::buildMSU(SS7MsgISUP::Type type, unsigned char sio,
|
||||
|
@ -2572,12 +2577,6 @@ bool SS7ISUP::processMSU(SS7MsgISUP::Type type, unsigned int cic,
|
|||
}
|
||||
|
||||
switch (msg->type()) {
|
||||
case SS7MsgISUP::RLC:
|
||||
// Just reset the circuit if it's a response to RSC request
|
||||
if (m_rscCic && m_rscCic->code() == msg->cic()) {
|
||||
resetCircuit(msg->cic(),false);
|
||||
break;
|
||||
}
|
||||
case SS7MsgISUP::IAM:
|
||||
case SS7MsgISUP::SAM:
|
||||
case SS7MsgISUP::ACM:
|
||||
|
@ -2588,6 +2587,11 @@ bool SS7ISUP::processMSU(SS7MsgISUP::Type type, unsigned int cic,
|
|||
case SS7MsgISUP::SGM:
|
||||
processCallMsg(msg,label,sls);
|
||||
break;
|
||||
case SS7MsgISUP::RLC:
|
||||
if (m_rscCic && m_rscCic->code() == msg->cic())
|
||||
processControllerMsg(msg,label,sls);
|
||||
else
|
||||
processCallMsg(msg,label,sls);
|
||||
default:
|
||||
processControllerMsg(msg,label,sls);
|
||||
}
|
||||
|
@ -2605,7 +2609,7 @@ SignallingEvent* SS7ISUP::processCircuitEvent(SignallingCircuitEvent& event,
|
|||
case SignallingCircuitEvent::NoAlarm:
|
||||
if (event.circuit())
|
||||
blockCircuit(event.circuit()->code(),
|
||||
event.type()==SignallingCircuitEvent::Alarm,false);
|
||||
event.type()==SignallingCircuitEvent::Alarm,false,true);
|
||||
break;
|
||||
default:
|
||||
Debug(this,DebugStub,"Unhandled circuit event (%u,%s) from call %p",
|
||||
|
@ -2614,7 +2618,6 @@ SignallingEvent* SS7ISUP::processCircuitEvent(SignallingCircuitEvent& event,
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Process call related messages
|
||||
void SS7ISUP::processCallMsg(SS7MsgISUP* msg, const SS7Label& label, int sls)
|
||||
{
|
||||
|
@ -2664,7 +2667,7 @@ void SS7ISUP::processCallMsg(SS7MsgISUP* msg, const SS7Label& label, int sls)
|
|||
flags &= ~SignallingCircuit::LockRemote;
|
||||
}
|
||||
else
|
||||
blockCircuit(msg->cic(),false,true);
|
||||
blockCircuit(msg->cic(),false,true,false);
|
||||
if (reserveCircuit(circuit,flags,&s,true)) {
|
||||
call = new SS7ISUPCall(this,circuit,label.dpc(),label.opc(),false,sls);
|
||||
m_calls.append(call);
|
||||
|
@ -2691,43 +2694,58 @@ void SS7ISUP::processCallMsg(SS7MsgISUP* msg, const SS7Label& label, int sls)
|
|||
}
|
||||
}
|
||||
|
||||
unsigned int getRangeAndStatus(NamedList& nl, unsigned int minRange, unsigned int maxRange,
|
||||
unsigned int maxMap = 0, String* map = 0, bool* hwFail = 0)
|
||||
{
|
||||
unsigned int range = nl.getIntValue("RangeAndStatus");
|
||||
if (range < minRange || range > maxRange)
|
||||
return 0;
|
||||
if (!maxMap)
|
||||
return range;
|
||||
NamedString* ns = nl.getParam("RangeAndStatus.map");
|
||||
if (!ns || ns->length() > maxMap || ns->length() < range)
|
||||
return 0;
|
||||
map = ns;
|
||||
if (hwFail) {
|
||||
ns = nl.getParam("GroupSupervisionTypeIndicator");
|
||||
*hwFail = (ns && *ns == "hw-failure");
|
||||
}
|
||||
return range;
|
||||
}
|
||||
|
||||
// Process controller related messages
|
||||
// Q.764 2.1.12: stop waiting for SGM if message is not: COT,BLK,BLA,UBL,UBA,CGB,CGA,CGU,CUA,CQM,CQR
|
||||
void SS7ISUP::processControllerMsg(SS7MsgISUP* msg, const SS7Label& label, int sls)
|
||||
{
|
||||
const char* reason = 0;
|
||||
bool impl = true;
|
||||
bool stopSGM = true;
|
||||
bool stopSGM = false;
|
||||
switch (msg->type()) {
|
||||
case SS7MsgISUP::CNF: // Confusion
|
||||
Debug(this,DebugNote,"%s with cause='%s' diagnostic='%s'",msg->name(),
|
||||
msg->params().getValue("CauseIndicators"),msg->params().getValue("CauseIndicators.diagnostic"));
|
||||
stopSGM = true;
|
||||
break;
|
||||
case SS7MsgISUP::RLC: // Release Complete
|
||||
if (m_rscCic && m_rscCic->code() == msg->cic())
|
||||
resetCircuit(msg->cic(),false);
|
||||
else
|
||||
reason = "unknown-channel";
|
||||
break;
|
||||
case SS7MsgISUP::RSC: // Reset Circuit
|
||||
if (resetCircuit(msg->cic(),true))
|
||||
transmitRLC(this,msg->cic(),label,true,sls);
|
||||
else
|
||||
reason = "unknown CIC";
|
||||
break;
|
||||
case SS7MsgISUP::UBL: // Unblocking
|
||||
case SS7MsgISUP::BLK: // Blocking
|
||||
{
|
||||
bool block = (msg->type() == SS7MsgISUP::BLK);
|
||||
if (blockCircuit(msg->cic(),block,true))
|
||||
transmitMessage(new SS7MsgISUP(block ? SS7MsgISUP::BLA : SS7MsgISUP::UBA,msg->cic()),label,true,sls);
|
||||
else
|
||||
reason = "unknown CIC";
|
||||
}
|
||||
stopSGM = false;
|
||||
reason = "unknown-channel";
|
||||
stopSGM = true;
|
||||
break;
|
||||
case SS7MsgISUP::GRS: // Circuit Group Reset
|
||||
stopSGM = true;
|
||||
{
|
||||
String rs = msg->params().getValue("RangeAndStatus");
|
||||
unsigned int n = rs.toInteger();
|
||||
// Q.763 3.43
|
||||
if (n < 1 || n > 31) {
|
||||
reason = "invalid range";
|
||||
transmitCNF(this,msg->cic(),label,true,sls,"wrong-message");
|
||||
// Q.763 3.43 min=1 max=31
|
||||
unsigned int n = getRangeAndStatus(msg->params(),1,31);
|
||||
if (!n) {
|
||||
reason = "invalid-ie";
|
||||
break;
|
||||
}
|
||||
String map('0',n);
|
||||
|
@ -2736,68 +2754,79 @@ void SS7ISUP::processControllerMsg(SS7MsgISUP* msg, const SS7Label& label, int s
|
|||
if (!resetCircuit(msg->cic()+i,true))
|
||||
d[i] = '1';
|
||||
SS7MsgISUP* m = new SS7MsgISUP(SS7MsgISUP::GRA,msg->cic());
|
||||
m->params().addParam("RangeAndStatus",rs);
|
||||
m->params().addParam("RangeAndStatus",String(n));
|
||||
m->params().addParam("RangeAndStatus.map",map);
|
||||
transmitMessage(m,label,true,sls);
|
||||
}
|
||||
break;
|
||||
case SS7MsgISUP::BLA: // Blocking Acknowledgement
|
||||
case SS7MsgISUP::UBL: // Unblocking
|
||||
if (blockCircuit(msg->cic(),false,true,false))
|
||||
transmitMessage(new SS7MsgISUP(SS7MsgISUP::UBA,msg->cic()),label,true,sls);
|
||||
else
|
||||
reason = "unknown-channel";
|
||||
break;
|
||||
case SS7MsgISUP::BLK: // Blocking
|
||||
if (blockCircuit(msg->cic(),true,true,false))
|
||||
transmitMessage(new SS7MsgISUP(SS7MsgISUP::BLA,msg->cic()),label,true,sls);
|
||||
else
|
||||
reason = "unknown-channel";
|
||||
break;
|
||||
case SS7MsgISUP::UBA: // Unblocking Acknowledgement
|
||||
if (!blockCircuit(msg->cic(),false,false,false))
|
||||
reason = "unknown-channel";
|
||||
break;
|
||||
case SS7MsgISUP::BLA: // Blocking Acknowledgement
|
||||
if (!blockCircuit(msg->cic(),true,false,false))
|
||||
reason = "unknown-channel";
|
||||
break;
|
||||
case SS7MsgISUP::GRA: // Circuit Group Reset Acknowledgement
|
||||
stopSGM = true;
|
||||
case SS7MsgISUP::CGA: // Circuit Group Blocking Acknowledgement
|
||||
case SS7MsgISUP::CUA: // Circuit Group Unblocking Acknowledgement
|
||||
case SS7MsgISUP::CQR: // Circuit Group Query Response (national use)
|
||||
stopSGM = false;
|
||||
case SS7MsgISUP::GRA: // Circuit Group Reset Acknowledgement
|
||||
reason = "unexpected response";
|
||||
transmitCNF(this,msg->cic(),label,true,sls,"wrong-state-message");
|
||||
reason = "wrong-state-message";
|
||||
break;
|
||||
case SS7MsgISUP::CGB: // Circuit Group Blocking
|
||||
case SS7MsgISUP::CGU: // Circuit Group Unblocking
|
||||
// Don't stop receiving segments
|
||||
stopSGM = false;
|
||||
// Q.763 3.43 range can be 1..256
|
||||
// Bit: 0-no indication 1-block/unblock(ack)
|
||||
// Bit: 0-no indication 1-block/unblock
|
||||
{
|
||||
String rs = msg->params().getValue("RangeAndStatus");
|
||||
NamedString* srcMap = msg->params().getParam("RangeAndStatus.map");
|
||||
unsigned int nCics = rs.toInteger();
|
||||
bool validMap = (srcMap && srcMap->length() <= 256 && srcMap->length() >= nCics);
|
||||
if (!validMap || nCics < 1 || nCics > 256) {
|
||||
reason = validMap ? "invalid range" : "invalid circuit map";
|
||||
transmitCNF(this,msg->cic(),label,true,sls,"wrong-message");
|
||||
String* srcMap = 0;
|
||||
bool hwFail = false;
|
||||
unsigned int nCics = getRangeAndStatus(msg->params(),1,256,256,srcMap,&hwFail);
|
||||
if (!nCics) {
|
||||
reason = "invalid-ie";
|
||||
break;
|
||||
}
|
||||
bool block = (msg->type() == SS7MsgISUP::CGB);
|
||||
if (nCics > srcMap->length())
|
||||
nCics = srcMap->length();
|
||||
String map('0',nCics);
|
||||
String map('0',srcMap->length());
|
||||
char* d = (char*)map.c_str();
|
||||
// TODO: Max bits set to 1 should be 32
|
||||
for (unsigned int i = 0; i < nCics; i++)
|
||||
if ((*srcMap)[i] != '0' && blockCircuit(msg->cic()+i,block,true))
|
||||
for (unsigned int i = 0; i < srcMap->length(); i++)
|
||||
if ((*srcMap)[i] != '0' && blockCircuit(msg->cic()+i,block,true,hwFail))
|
||||
d[i] = '1';
|
||||
SS7MsgISUP* m = new SS7MsgISUP(block?SS7MsgISUP::CGA:SS7MsgISUP::CUA,msg->cic());
|
||||
m->params().copyParam(msg->params(),"GroupSupervisionTypeIndicator");
|
||||
m->params().addParam("RangeAndStatus",String(nCics));
|
||||
m->params().addParam("RangeAndStatus.map",map);
|
||||
m->params().copyParam(msg->params(),"GroupSupervisionTypeIndicator");
|
||||
transmitMessage(m,label,true,sls);
|
||||
}
|
||||
break;
|
||||
case SS7MsgISUP::CQM: // Circuit Group Query (national use)
|
||||
case SS7MsgISUP::COT: // Continuity
|
||||
stopSGM = false;
|
||||
default:
|
||||
impl = false;
|
||||
reason = "not implemented";
|
||||
transmitCNF(this,msg->cic(),label,true,sls,"service-not-implemented");
|
||||
reason = "service-not-implemented";
|
||||
}
|
||||
if (stopSGM) {
|
||||
SS7ISUPCall* call = findCall(msg->cic());
|
||||
if (call)
|
||||
call->stopWaitSegment(false);
|
||||
}
|
||||
if (reason)
|
||||
if (reason) {
|
||||
Debug(this,impl?DebugNote:DebugStub,"'%s' with cic=%u: %s",msg->name(),msg->cic(),reason);
|
||||
transmitCNF(this,msg->cic(),label,true,sls,reason);
|
||||
}
|
||||
}
|
||||
|
||||
// Replace a call's circuit if checkCall is true
|
||||
|
@ -2833,16 +2862,30 @@ bool SS7ISUP::resetCircuit(unsigned int cic, bool checkCall)
|
|||
|
||||
// Block/unblock a circuit
|
||||
// See Q.764 2.8.2
|
||||
bool SS7ISUP::blockCircuit(unsigned int cic, bool block, bool remote)
|
||||
bool SS7ISUP::blockCircuit(unsigned int cic, bool block, bool remote, bool hwFail)
|
||||
{
|
||||
SignallingCircuit* circuit = circuits() ? circuits()->find(cic) : 0;
|
||||
if (!circuit)
|
||||
return false;
|
||||
int flag = remote ? SignallingCircuit::LockRemote : SignallingCircuit::LockLocal;
|
||||
int lockFlag = 0;
|
||||
int hwFlag = 0;
|
||||
if (remote) {
|
||||
lockFlag = SignallingCircuit::LockRemote;
|
||||
if (hwFail)
|
||||
hwFlag = SignallingCircuit::LockRemoteHWFailure;
|
||||
}
|
||||
else {
|
||||
lockFlag = SignallingCircuit::LockLocal;
|
||||
if (hwFail)
|
||||
hwFlag = SignallingCircuit::LockLocalHWFailure;
|
||||
}
|
||||
// Already blocked/unblocked ?
|
||||
if (block == (0 != circuit->locked(flag)))
|
||||
if (block == (0 != circuit->locked(lockFlag))) {
|
||||
circuit->setLock(hwFlag);
|
||||
return true;
|
||||
Debug(this,DebugNote,"%slocking %s side of the circuit %u",block?"B":"Unb",remote?"remote":"local",cic);
|
||||
}
|
||||
Debug(this,DebugNote,"%slocking %s side of the circuit %u%s",
|
||||
block?"B":"Unb",remote?"remote":"local",cic,(hwFlag)?": HW failure":"");
|
||||
// Replace circuit for call (Q.764 2.8.2.1)
|
||||
SS7ISUPCall* call = findCall(cic);
|
||||
if (call && call->outgoing() && call->state() == SS7ISUPCall::Setup) {
|
||||
|
@ -2850,12 +2893,13 @@ bool SS7ISUP::blockCircuit(unsigned int cic, bool block, bool remote)
|
|||
reserveCircuit(newCircuit);
|
||||
call->replaceCircuit(newCircuit);
|
||||
}
|
||||
lockFlag |= hwFlag;
|
||||
if (!remote)
|
||||
flag |= SignallingCircuit::LockLocalChanged;
|
||||
lockFlag |= SignallingCircuit::LockLocalChanged;
|
||||
if (block)
|
||||
circuit->setLock(flag);
|
||||
circuit->setLock(lockFlag);
|
||||
else
|
||||
circuit->resetLock(flag);
|
||||
circuit->resetLock(lockFlag);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,13 @@
|
|||
|
||||
using namespace TelEngine;
|
||||
|
||||
static TokenDict s_dictCicLock[] = {
|
||||
{"local", SignallingCircuit::LockLocal},
|
||||
{"remote", SignallingCircuit::LockRemote},
|
||||
{"localchanged", SignallingCircuit::LockLocalChanged},
|
||||
{0,0},
|
||||
};
|
||||
|
||||
/**
|
||||
* SignallingCallControl
|
||||
*/
|
||||
|
@ -36,6 +43,7 @@ SignallingCallControl::SignallingCallControl(const NamedList& params,
|
|||
const char* msgPrefix)
|
||||
: Mutex(true),
|
||||
m_circuits(0),
|
||||
m_cicLock(0),
|
||||
m_strategy(SignallingCircuitGroup::Increment),
|
||||
m_exiting(false),
|
||||
m_dumper(0)
|
||||
|
@ -58,6 +66,9 @@ SignallingCallControl::SignallingCallControl(const NamedList& params,
|
|||
|
||||
// Message prefix
|
||||
m_msgPrefix = params.getValue("message-prefix",msgPrefix);
|
||||
|
||||
// Circuit lock
|
||||
SignallingUtils::encodeFlags(0,m_cicLock,params.getValue("lockcircuits"),s_dictCicLock);
|
||||
}
|
||||
|
||||
SignallingCallControl::~SignallingCallControl()
|
||||
|
@ -84,8 +95,14 @@ void SignallingCallControl::attach(SignallingCircuitGroup* circuits)
|
|||
"SignallingCallControl. Replaced circuit group (%p) with (%p) [%p]",
|
||||
m_circuits,circuits,this);
|
||||
m_circuits = circuits;
|
||||
if (m_circuits)
|
||||
if (m_circuits) {
|
||||
Lock lock(m_circuits);
|
||||
m_circuits->setStrategy(m_strategy);
|
||||
DDebug(DebugAll,"SignallingCallControl. Attached group (%p) lock=%d [%p]",
|
||||
m_circuits,m_cicLock,this);
|
||||
for (ObjList* o = m_circuits->circuits().skipNull(); o; o = o->skipNext())
|
||||
(static_cast<SignallingCircuit*>(o->get()))->setLock(m_cicLock);
|
||||
}
|
||||
}
|
||||
|
||||
// Reserve a circuit from a given list in attached group
|
||||
|
|
|
@ -689,7 +689,8 @@ public:
|
|||
unsigned int circuitCount();
|
||||
|
||||
/**
|
||||
* Attach/detach a circuit group to this call controller. Set group's allocation strategy
|
||||
* Attach/detach a circuit group to this call controller. Set group's allocation strategy.
|
||||
* Set locked flags for all circuits belonging to the attached circuit group.
|
||||
* Cleanup controller before detaching the group or attaching a new one
|
||||
* This method is thread safe
|
||||
* @param circuits Pointer to the SignallingCircuitGroup to attach. 0 to detach and force a cleanup
|
||||
|
@ -834,6 +835,7 @@ protected:
|
|||
|
||||
private:
|
||||
SignallingCircuitGroup* m_circuits; // Circuit group
|
||||
int m_cicLock; // Flags to be locked when a circuit group is attached to this controller
|
||||
int m_strategy; // Strategy to allocate circuits for outgoing calls
|
||||
bool m_exiting; // Call control is terminating. Generate a Disable event when no more calls
|
||||
SignallingDumper* m_dumper; // Data dumper in use
|
||||
|
@ -1168,9 +1170,11 @@ public:
|
|||
* Lock circuit flags
|
||||
*/
|
||||
enum LockFlags {
|
||||
LockLocal = 1,
|
||||
LockRemote = 2,
|
||||
LockLocalChanged = 4,
|
||||
LockLocal = 0x0001, // Local side of the circuit is locked
|
||||
LockRemote = 0x0002, // Remote side of the circuit is locked
|
||||
LockLocalHWFailure = 0x0004, // Local side of the circuit is locked due to HW failure
|
||||
LockRemoteHWFailure = 0x0008, // Remote side of the circuit is locked due to HW failure
|
||||
LockLocalChanged = 0x0010, // Local side of the circuit is locked
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -5143,7 +5147,7 @@ private:
|
|||
bool resetCircuit(unsigned int cic, bool checkCall);
|
||||
// Block/unblock a circuit side (local or remote)
|
||||
// Return false if the given circuit doesn't exist
|
||||
bool blockCircuit(unsigned int cic, bool block, bool remote);
|
||||
bool blockCircuit(unsigned int cic, bool block, bool remote, bool hwFail);
|
||||
// Find a call by its circuit identification code
|
||||
SS7ISUPCall* findCall(unsigned int cic);
|
||||
|
||||
|
|
Loading…
Reference in New Issue