Reimplemented circuit (un)blocking.

git-svn-id: http://voip.null.ro/svn/yate@1807 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
marian 2008-03-19 11:11:19 +00:00
parent 46b9062a7a
commit bddcc8363a
2 changed files with 148 additions and 38 deletions

View File

@ -1972,7 +1972,8 @@ SS7ISUP::SS7ISUP(const NamedList& params)
m_rscTimer(0),
m_rscCic(0),
m_lockTimer(0),
m_lockCic(false),
m_lockNeed(true),
m_lockFlags(0),
m_lockCicCode(0)
{
setName(params.getValue("debugname","isup"));
@ -2210,15 +2211,15 @@ void SS7ISUP::timerTick(const Time& when)
return;
// Blocking/unblocking circuits
if (m_lockCicCode < circuits()->last() && m_lockTimer.interval()) {
if (m_lockNeed) {
if (m_lockTimer.started()) {
if (!m_lockTimer.timeout(when.msec()))
return;
m_lockTimer.stop();
Debug(this,DebugMild,"Circuit %sblocking timed out for cic=%u",
m_lockCic?"":"un",m_lockCicCode);
Debug(this,DebugMild,"Circuit %sblocking timed out cic=%u map=%s",
(m_lockFlags&SignallingCircuit::LockLocal)?"":"un",
m_lockCicCode,m_lockMap.c_str());
}
if (notifyLock())
if (sendLocalLock(when.msec()))
return;
}
@ -2626,9 +2627,13 @@ SignallingEvent* SS7ISUP::processCircuitEvent(SignallingCircuitEvent& event,
case SignallingCircuitEvent::Alarm:
case SignallingCircuitEvent::NoAlarm:
if (event.circuit()) {
blockCircuit(event.circuit()->code(),
event.type()==SignallingCircuitEvent::Alarm,false,true);
event.circuit()->setLock(SignallingCircuit::LockLocalChanged);
lock();
// TODO: check if the circuit should be locked now or when received the response
// blockCircuit(event.circuit()->code(),
// event.type()==SignallingCircuitEvent::Alarm,false,true);
event.circuit()->setLock(SignallingCircuit::LockLocalChanged | SignallingCircuit::LockLocalHWFailure);
m_lockNeed = true;
unlock();
}
break;
default:
@ -2740,6 +2745,9 @@ void SS7ISUP::processControllerMsg(SS7MsgISUP* msg, const SS7Label& label, int s
const char* reason = 0;
bool impl = true;
bool stopSGM = false;
// TODO: Check if segmentation shoud stop for all affected circuits received withing range (CGB,GRS, ...)
switch (msg->type()) {
case SS7MsgISUP::CNF: // Confusion
Debug(this,DebugNote,"%s with cause='%s' diagnostic='%s'",msg->name(),
@ -2790,24 +2798,63 @@ void SS7ISUP::processControllerMsg(SS7MsgISUP* msg, const SS7Label& label, int s
break;
case SS7MsgISUP::UBA: // Unblocking Acknowledgement
case SS7MsgISUP::BLA: // Blocking Acknowledgement
if (msg->cic() == m_lockCicCode) {
bool block = (msg->type() == SS7MsgISUP::BLA);
if (blockCircuit(msg->cic(),block,false,false)) {
SignallingCircuit* cic = circuits() ? circuits()->find(msg->cic()) : 0;
if (cic)
cic->resetLock(SignallingCircuit::LockLocalChanged);
{
int l = (msg->type() == SS7MsgISUP::BLA) ? SignallingCircuit::LockLocal : 0;
// Check for correct response: same msg type and circuit code
if (msg->cic() != m_lockCicCode || l != m_lockFlags ||
m_lockMap.length() != 1) {
reason = "wrong-state-message";
break;
}
else
if (!blockCircuit(msg->cic(),m_lockFlags,false,false)) {
reason = "unknown-channel";
notifyLock();
break;
}
SignallingCircuit* cic = circuits() ? circuits()->find(msg->cic()) : 0;
if (cic)
cic->resetLock(SignallingCircuit::LockLocalChanged);
sendLocalLock();
}
else
reason = "wrong-state-message";
break;
case SS7MsgISUP::GRA: // Circuit Group Reset Acknowledgement
stopSGM = true;
case SS7MsgISUP::CGA: // Circuit Group Blocking Acknowledgement
case SS7MsgISUP::CUA: // Circuit Group Unblocking Acknowledgement
// Q.763 3.43 range can be 1..256
// Bit: 0-no indication 1-block/unblock
{
String* srcMap = 0;
bool hwFail = false;
unsigned int nCics = getRangeAndStatus(msg->params(),1,256,256,srcMap,&hwFail);
if (!nCics) {
reason = "invalid-ie";
break;
}
int l = 0;
if (msg->type() == SS7MsgISUP::CGA)
l |= SignallingCircuit::LockLocal;
if (hwFail)
l |= SignallingCircuit::LockLocalHWFailure;
// Check for correct response: same msg type, circuit code, type indicator, circuit map
bool ok = (msg->cic() == m_lockCicCode || l == m_lockFlags || m_lockMap.length() == nCics);
if (ok)
for (unsigned int i = 0; i < m_lockMap.length(); i++)
if (m_lockMap[i] == '0' && srcMap->at(i) != '0') {
ok = false;
break;
}
if (!ok) {
reason = "wrong-state-message";
break;
}
bool block = (0 != (m_lockFlags & SignallingCircuit::LockLocal));
// TODO: Max bits set to 1 should be 32
for (unsigned int i = 0; i < m_lockMap.length(); i++)
if (m_lockMap[i] != '0')
blockCircuit(msg->cic()+i,block,true,hwFail);
sendLocalLock();
}
break;
case SS7MsgISUP::GRA: // Circuit Group Reset Acknowledgement
// TODO: stop receiving segments
case SS7MsgISUP::CQR: // Circuit Group Query Response (national use)
reason = "wrong-state-message";
break;
@ -2838,9 +2885,9 @@ void SS7ISUP::processControllerMsg(SS7MsgISUP* msg, const SS7Label& label, int s
}
break;
case SS7MsgISUP::UEC: // Unequipped CIC (national use)
Debug(this,DebugWarn,"%s for cic=%u",msg->name(),msg->cic());
Debug(this,DebugWarn,"%s for cic=%u. Circuit is unequipped on remote side",
msg->name(),msg->cic());
blockCircuit(msg->cic(),true,true,false);
blockCircuit(msg->cic(),true,false,false);
break;
case SS7MsgISUP::CQM: // Circuit Group Query (national use)
case SS7MsgISUP::COT: // Continuity
@ -2943,29 +2990,87 @@ SS7ISUPCall* SS7ISUP::findCall(unsigned int cic)
}
// Send blocking/unblocking messages
bool SS7ISUP::notifyLock()
// Return false if no request was sent
bool SS7ISUP::sendLocalLock(u_int64_t when)
{
m_lockTimer.stop();
m_lockCicCode++;
#define LOCK_FLAGS (SignallingCircuit::LockLocal | SignallingCircuit::LockLocalHWFailure)
if (!circuits())
return false;
for (ObjList* o = circuits()->circuits().skipNull(); o; o = o->skipNext()) {
// Reset all lock related data
m_lockTimer.stop();
m_lockNeed = false;
m_lockCicCode = 0;
m_lockMap.clear();
// Peek a starting circuit whose local state changed
ObjList* o = circuits()->circuits().skipNull();
SignallingCircuitSpan* span = 0;
for (; o; o = o->skipNext()) {
SignallingCircuit* cic = static_cast<SignallingCircuit*>(o->get());
if (cic->code() < m_lockCicCode)
continue;
m_lockCicCode = cic->code();
if (!cic->locked(SignallingCircuit::LockLocalChanged))
continue;
m_lockCic = (0 != cic->locked(SignallingCircuit::LockLocal));
m_lockNeed = true;
m_lockCicCode = cic->code();
m_lockFlags = cic->locked(LOCK_FLAGS);
span = cic->span();
o = o->skipNext();
break;
}
if (m_lockCicCode >= circuits()->last())
if (!m_lockNeed)
return false;
m_lockTimer.start();
SS7MsgISUP* msg = new SS7MsgISUP(m_lockCic?SS7MsgISUP::BLK:SS7MsgISUP::UBL,m_lockCicCode);
// Check if we can pick a range of circuits within the same span
// with the same operation to do
// Q.763 3.43: range can be 2..256. Bit: 0-no indication 1-block/unblock.
// Max bits set to 1 must be 32
char d[256];
d[0] = '1';
unsigned int cics = 1;
unsigned int lockRange = 1;
for (; o && cics < 32; o = o->skipNext(), lockRange++) {
SignallingCircuit* cic = static_cast<SignallingCircuit*>(o->get());
if (span != cic->span())
break;
// Add circuit to map
// Circuit must have the lock state changed and the same lock flags as the base circuit's
if (0 != cic->locked(SignallingCircuit::LockLocalChanged) &&
m_lockFlags == cic->locked(LOCK_FLAGS)) {
d[lockRange] = '1';
cics++;
}
}
if (cics == 1)
lockRange = 1;
// Build and send the message
SS7MsgISUP* msg = 0;
m_lockMap.assign(d,lockRange);
if (m_lockMap.length() > 1) {
if (m_lockFlags & SignallingCircuit::LockLocal)
msg = new SS7MsgISUP(SS7MsgISUP::CGB,m_lockCicCode);
else
msg = new SS7MsgISUP(SS7MsgISUP::CGU,m_lockCicCode);
if (m_lockFlags & SignallingCircuit::LockLocalHWFailure)
msg->params().addParam("GroupSupervisionTypeIndicator","hw-failure");
else
msg->params().addParam("GroupSupervisionTypeIndicator","maintenance");
msg->params().addParam("RangeAndStatus",String(m_lockMap.length()));
msg->params().addParam("RangeAndStatus.map",m_lockMap);
}
else {
if (m_lockFlags & SignallingCircuit::LockLocal)
msg = new SS7MsgISUP(SS7MsgISUP::BLK,m_lockCicCode);
else
msg = new SS7MsgISUP(SS7MsgISUP::UBL,m_lockCicCode);
// Reset all flags except for LockLocal
m_lockFlags &= ~SignallingCircuit::LockLocalHWFailure;
}
SS7Label label(m_type,*m_remotePoint,*m_defPoint,m_sls);
transmitMessage(msg,label,false);
m_lockTimer.start(when);
return true;
#undef LOCK_FLAGS
}

View File

@ -5153,7 +5153,8 @@ private:
// Find a call by its circuit identification code
SS7ISUPCall* findCall(unsigned int cic);
// Send blocking/unblocking messages
bool notifyLock();
// Return false if no request was sent
bool sendLocalLock(u_int64_t when = Time::msecNow());
SS7PointCode::Type m_type; // Point code type of this call controller
ObjList m_pointCodes; // Point codes serviced by this call controller
@ -5168,11 +5169,15 @@ private:
String m_numScreening; // Number screening
String m_callerCat; // Caller party category
String m_format; // Default format
// Circuit reset
SignallingTimer m_rscTimer; // RSC message or idle timeout
SignallingCircuit* m_rscCic; // Circuit currently beeing reset
SignallingTimer m_lockTimer; // Block/unblock timer
bool m_lockCic; // Currently blocking or unblocking circuit
unsigned int m_lockCicCode; // Last blocked/unblocked circuit
// Blocking/unblocking circuits
SignallingTimer m_lockTimer; // Request timeout
bool m_lockNeed; // Flag used to signal that there are circuits whose lock state changed
int m_lockFlags; // Current request flags: blocking/unblocking,hw-failure/maintenance
unsigned int m_lockCicCode; // Current (un)blocking cic code
String m_lockMap; // The sent circuit map (contains 1 element for single circuit request)
};
/**