Check pending (un)block messages for valid circuits when timed out. Fixed bug: remove conflicting CGB/CGU only if GroupSupervisionTypeIndicator is the same.

git-svn-id: http://yate.null.ro/svn/yate/trunk@5323 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
marian 2012-11-15 11:32:33 +00:00
parent 5baf162253
commit aab6f9cc37
2 changed files with 130 additions and 6 deletions

View File

@ -3812,6 +3812,28 @@ void SS7ISUP::destroyed()
SS7Layer4::destroyed();
}
// Utility: find a pending (un)block message for a given circuit
static bool findPendingMsgTimerLock(ObjList& list, unsigned int code)
{
for (ObjList* o = list.skipNull(); o; o = o->skipNext()) {
SignallingMessageTimer* m = static_cast<SignallingMessageTimer*>(o->get());
SS7MsgISUP* msg = static_cast<SS7MsgISUP*>(m->message());
if (!msg || code < msg->cic())
continue;
if (msg->type() == SS7MsgISUP::BLK || msg->type() == SS7MsgISUP::UBL) {
if (msg->cic() == code)
return true;
continue;
}
if (msg->type() != SS7MsgISUP::CGB && msg->type() != SS7MsgISUP::CGU)
continue;
const String& map = msg->params()[YSTRING("RangeAndStatus.map")];
if (map[code - msg->cic()] == '1')
return true;
}
return false;
}
void SS7ISUP::timerTick(const Time& when)
{
Lock mylock(this,SignallingEngine::maxLockWait());
@ -3887,6 +3909,80 @@ void SS7ISUP::timerTick(const Time& when)
continue;
}
}
// Check if message is still in use
if (msg->type() == SS7MsgISUP::CGB || msg->type() == SS7MsgISUP::CGU) {
String* map = msg->params().getParam(YSTRING("RangeAndStatus.map"));
bool ok = !TelEngine::null(map);
String removedCics;
if (ok) {
unsigned int nCics = 0;
int flg = 0;
int flgReset = 0;
if ((msg->params()[YSTRING("GroupSupervisionTypeIndicator")] == YSTRING("hw-failure"))) {
flg = SignallingCircuit::LockLocalHWFail;
flgReset = SignallingCircuit::LockingHWFail;
}
else {
flg = SignallingCircuit::LockLocalMaint;
flgReset = SignallingCircuit::LockingMaint;
}
int on = (msg->type() == SS7MsgISUP::CGB) ? flg : 0;
char* s = (char*)map->c_str();
for (unsigned int i = 0; i < map->length(); i++) {
if (s[i] == '0')
continue;
unsigned int code = msg->cic() + i;
SignallingCircuit* cic = circuits()->find(code);
if (cic && (on == cic->locked(flg))) {
nCics++;
continue;
}
// Don't reset locking flag if there is another operation in progress
if (cic && !(findPendingMsgTimerLock(m_pending,code) ||
findPendingMsgTimerLock(reInsert,code)) && cic->locked(flgReset)) {
cic->resetLock(flgReset);
Debug(this,DebugNote,"Pending %s reset flag=0x%x cic=%u current=0x%x",
msg->name(),flgReset,code,cic->locked());;
}
s[i] = '0';
removedCics.append(String(code),",");
}
if (nCics)
msg->params().setParam("RangeAndStatus",String(nCics));
else
ok = false;
}
if (!ok) {
Debug(this,DebugNote,"Removed empty pending operation '%s' cic=%u",
msg->name(),msg->cic());
TelEngine::destruct(m);
continue;
}
if (removedCics)
Debug(this,DebugAll,"Removed cics=%s from pending operation '%s' map cic=%u",
removedCics.c_str(),msg->name(),msg->cic());
}
else if (msg->type() == SS7MsgISUP::BLK || msg->type() == SS7MsgISUP::UBL) {
// We set the following param when sending BLK/UBL for HW fail reason
bool maint = !msg->params().getBoolValue(YSTRING("isup_pending_block_hwfail"));
int flg = maint ? SignallingCircuit::LockLocalMaint : SignallingCircuit::LockLocalHWFail;
int on = (msg->type() == SS7MsgISUP::BLK) ? flg : 0;
SignallingCircuit* cic = circuits()->find(msg->cic());
if (!cic || on != cic->locked(flg)) {
flg = maint ? SignallingCircuit::LockingMaint : SignallingCircuit::LockingHWFail;
// Don't reset locking flag if there is another operation in progress
if (cic && !(findPendingMsgTimerLock(m_pending,msg->cic()) ||
findPendingMsgTimerLock(reInsert,msg->cic())) && cic->locked(flg)) {
cic->resetLock(flg);
Debug(this,DebugNote,"Pending %s reset flag=0x%x cic=%u current=0x%x",
msg->name(),flg,cic->code(),cic->locked());
}
Debug(this,DebugNote,"Removed empty pending operation '%s' cic=%u",
msg->name(),msg->cic());
TelEngine::destruct(m);
continue;
}
}
bool alert = msg->params().getBoolValue(YSTRING("isup_alert_maint"));
const char* reason = msg->params().getValue(YSTRING("isup_pending_reason"),"");
Debug(this,!alert ? DebugAll : DebugMild,
@ -5672,6 +5768,23 @@ SignallingMessageTimer* SS7ISUP::findPendingMessage(SS7MsgISUP::Type type, unsig
return 0;
}
// Retrieve a pending message with given parameter
SignallingMessageTimer* SS7ISUP::findPendingMessage(SS7MsgISUP::Type type, unsigned int cic,
const String& param, const String& value, bool remove)
{
Lock lock(this);
for (ObjList* o = m_pending.skipNull(); o; o = o->skipNext()) {
SignallingMessageTimer* m = static_cast<SignallingMessageTimer*>(o->get());
SS7MsgISUP* msg = static_cast<SS7MsgISUP*>(m->message());
if (msg && msg->type() == type && msg->cic() == cic && msg->params()[param] == value) {
if (remove)
o->remove(false);
return m;
}
}
return 0;
}
// Transmit a list of messages. Return true if at least 1 message was sent
bool SS7ISUP::transmitMessages(ObjList& list)
{
@ -5860,12 +5973,20 @@ bool SS7ISUP::handleCicBlockCommand(const NamedList& p, bool block)
}
if (SS7MsgISUP::Unknown != remove) {
bool removed = false;
for (;;) {
SignallingMessageTimer* pending = findPendingMessage(remove,msg->cic(),true);
if (!pending)
break;
TelEngine::destruct(pending);
removed = true;
SignallingMessageTimer* pending = 0;
if (remove != SS7MsgISUP::CGB && remove != SS7MsgISUP::CGU) {
while (0 != (pending = findPendingMessage(remove,msg->cic(),true))) {
TelEngine::destruct(pending);
removed = true;
}
}
else {
NamedString* ns = msg->params().getParam(YSTRING("GroupSupervisionTypeIndicator"));
while (ns &&
0 != (pending = findPendingMessage(remove,msg->cic(),ns->name(),*ns,true))) {
TelEngine::destruct(pending);
removed = true;
}
}
if (removed)
Debug(this,DebugNote,"Removed pending operation '%s' cic=%u",

View File

@ -9013,6 +9013,9 @@ private:
// Retrieve a pending message
SignallingMessageTimer* findPendingMessage(SS7MsgISUP::Type type, unsigned int cic,
bool remove = false);
// Retrieve a pending message with given parameter
SignallingMessageTimer* findPendingMessage(SS7MsgISUP::Type type, unsigned int cic,
const String& param, const String& value, bool remove = false);
// Transmit a list of messages. Return true if at least 1 message was sent
bool transmitMessages(ObjList& list);
// Handle circuit(s) (un)block command