Changed the way MSU recovery and sequence retrieval work to accomodate the asynchronous nature of M2UA.
git-svn-id: http://yate.null.ro/svn/yate/trunk@3569 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
b0d3f6c656
commit
11419dded4
|
@ -214,11 +214,6 @@ bool SS7Layer2::control(NamedList& params)
|
|||
return (cmd >= 0) && control((Operation)cmd,¶ms);
|
||||
}
|
||||
|
||||
ObjList* SS7Layer2::recoverMSU()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool SS7Layer2::getEmergency(NamedList* params, bool emg) const
|
||||
{
|
||||
if (m_autoEmergency && !emg) {
|
||||
|
@ -568,24 +563,28 @@ bool SS7MTP2::transmitMSU(const SS7MSU& msu)
|
|||
}
|
||||
|
||||
// Remove the MSUs in the queue, the upper layer will move them to another link
|
||||
ObjList* SS7MTP2::recoverMSU()
|
||||
void SS7MTP2::recoverMSU(int sequence)
|
||||
{
|
||||
lock();
|
||||
ObjList* lst = 0;
|
||||
for (;;) {
|
||||
lock();
|
||||
DataBlock* pkt = static_cast<DataBlock*>(m_queue.remove(false));
|
||||
unlock();
|
||||
if (!pkt)
|
||||
break;
|
||||
if (pkt->length() > 3) {
|
||||
SS7MSU* msu = new SS7MSU(3 + (char*)pkt->data(),pkt->length() - 3);
|
||||
if (!lst)
|
||||
lst = new ObjList;
|
||||
lst->append(msu);
|
||||
unsigned char* head = pkt->data(0,4);
|
||||
if (head) {
|
||||
int seq = head[1] & 0x7f;
|
||||
if (sequence < 0 || ((seq - sequence) & 0x7f) < 0x3f) {
|
||||
sequence = -1;
|
||||
SS7MSU msu(head + 3,pkt->length() - 3);
|
||||
recoveredMSU(msu);
|
||||
}
|
||||
else
|
||||
Debug(this,DebugAll,"Not recovering MSU with seq=%d, requested %d",
|
||||
seq,sequence);
|
||||
}
|
||||
TelEngine::destruct(pkt);
|
||||
}
|
||||
unlock();
|
||||
return lst;
|
||||
}
|
||||
|
||||
// Decode a received packet into signalling units
|
||||
|
|
|
@ -642,6 +642,22 @@ int SS7MTP3::getSequence(int sls) const
|
|||
return false;
|
||||
}
|
||||
|
||||
void SS7MTP3::recoverMSU(int sls, int sequence)
|
||||
{
|
||||
if (sls < 0)
|
||||
return;
|
||||
const ObjList* l = &m_links;
|
||||
for (; l; l = l->next()) {
|
||||
L2Pointer* p = static_cast<L2Pointer*>(l->get());
|
||||
if (!(p && *p))
|
||||
continue;
|
||||
if ((*p)->sls() == sls) {
|
||||
(*p)->recoverMSU(sequence);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Attach a link in the first free SLS
|
||||
void SS7MTP3::attach(SS7Layer2* link)
|
||||
{
|
||||
|
@ -981,6 +997,36 @@ bool SS7MTP3::receivedMSU(const SS7MSU& msu, SS7Layer2* link, int sls)
|
|||
return (msu.getSIF() > SS7MSU::MTNS) && unavailable(msu,label,sls,handled.upu());
|
||||
}
|
||||
|
||||
bool SS7MTP3::recoveredMSU(const SS7MSU& msu, SS7Layer2* link, int sls)
|
||||
{
|
||||
int netType = msu.getNI();
|
||||
SS7PointCode::Type cpType = type(netType);
|
||||
unsigned int llen = SS7Label::length(cpType);
|
||||
if (!llen) {
|
||||
Debug(toString(),DebugWarn,"Recovered MSU but point code type is unconfigured [%p]",this);
|
||||
return false;
|
||||
}
|
||||
// check MSU length against SIO + label length
|
||||
if (msu.length() <= llen) {
|
||||
Debug(this,DebugWarn,"Recovered short MSU of length %u [%p]",
|
||||
msu.length(),this);
|
||||
return false;
|
||||
}
|
||||
SS7Label label(cpType,msu);
|
||||
#ifdef DEBUG
|
||||
if (debugAt(DebugInfo)) {
|
||||
String tmp;
|
||||
tmp << label << " (" << label.opc().pack(cpType) << ":" << label.dpc().pack(cpType) << ":" << label.sls() << ")";
|
||||
Debug(this,DebugAll,"Recovered MSU from link %d '%s' %p. Address: %s",
|
||||
sls,link->toString().c_str(),link,tmp.c_str());
|
||||
}
|
||||
#endif
|
||||
// first try to send on another active link in the linkset
|
||||
if (transmitMSU(msu,label,sls % m_total) >= 0)
|
||||
return true;
|
||||
return SS7Layer3::recoveredMSU(msu,label,sls);
|
||||
}
|
||||
|
||||
void SS7MTP3::notify(SS7Layer2* link)
|
||||
{
|
||||
Lock lock(this);
|
||||
|
|
|
@ -331,7 +331,6 @@ HandledMSU SS7Management::receivedMSU(const SS7MSU& msu, const SS7Label& label,
|
|||
len,msg,sls,tmp.c_str());
|
||||
}
|
||||
|
||||
// TODO: implement
|
||||
String addr;
|
||||
addr << label;
|
||||
if (msg->type() == SS7MsgSNM::TFP ||
|
||||
|
@ -386,8 +385,7 @@ HandledMSU SS7Management::receivedMSU(const SS7MSU& msu, const SS7Label& label,
|
|||
}
|
||||
else if (msg->type() == SS7MsgSNM::COO ||
|
||||
msg->type() == SS7MsgSNM::XCO ||
|
||||
msg->type() == SS7MsgSNM::ECO ||
|
||||
msg->type() == SS7MsgSNM::CBD) {
|
||||
msg->type() == SS7MsgSNM::ECO) {
|
||||
if (!len--)
|
||||
return false;
|
||||
const unsigned char* s = msu.getData(label.length()+2,len);
|
||||
|
@ -395,64 +393,19 @@ HandledMSU SS7Management::receivedMSU(const SS7MSU& msu, const SS7Label& label,
|
|||
return false;
|
||||
Debug(this,DebugAll,"%s (code len=%u) [%p]",msg->name(),len,this);
|
||||
SS7Label lbl(label,label.sls(),0);
|
||||
SS7MSU answer(msu.getSIO(),lbl,0,len+1);
|
||||
unsigned char* d = answer.getData(lbl.length()+1,len+1);
|
||||
if (!d)
|
||||
return false;
|
||||
switch (msg->type()) {
|
||||
case SS7MsgSNM::COO:
|
||||
*d++ = SS7MsgSNM::COA;
|
||||
break;
|
||||
case SS7MsgSNM::XCO:
|
||||
*d++ = SS7MsgSNM::XCA;
|
||||
break;
|
||||
case SS7MsgSNM::ECO:
|
||||
*d++ = SS7MsgSNM::ECA;
|
||||
break;
|
||||
case SS7MsgSNM::CBD:
|
||||
*d++ = SS7MsgSNM::CBA;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
while (len--)
|
||||
*d++ = *s++;
|
||||
return transmitMSU(answer,lbl,sls) >= 0;
|
||||
}
|
||||
else if (msg->type() == SS7MsgSNM::UPU) {
|
||||
Debug(this,DebugNote,"Unavailable part %s at %s, cause %s",
|
||||
msg->params().getValue("part","?"),
|
||||
msg->params().getValue("destination","?"),
|
||||
msg->params().getValue("cause","?"));
|
||||
}
|
||||
else if (msg->type() == SS7MsgSNM::CBA) {
|
||||
if (!len--)
|
||||
return false;
|
||||
Debug(this,DebugAll,"%s (code len=%u) [%p]",msg->name(),len,this);
|
||||
lock();
|
||||
SnmPending* pend = 0;
|
||||
for (ObjList* l = m_pending.skipNull(); l; l = l->skipNext()) {
|
||||
SnmPending* p = static_cast<SnmPending*>(l->get());
|
||||
if (p->msu().length() != msu.length())
|
||||
continue;
|
||||
const unsigned char* ptr = p->msu().getData(p->length()+1,len+1);
|
||||
if (!ptr || (ptr[0] != SS7MsgSNM::CBD))
|
||||
continue;
|
||||
if (::memcmp(ptr+1,buf+1,len) || !p->matches(label))
|
||||
continue;
|
||||
pend = static_cast<SnmPending*>(m_pending.remove(p,false));
|
||||
break;
|
||||
}
|
||||
unlock();
|
||||
if (pend) {
|
||||
if (inhibit(lbl,SS7Layer2::Inactive)) {
|
||||
String link;
|
||||
link << msg->params().getValue("pointcodetype") << "," << *pend;
|
||||
Debug(this,DebugNote,"Changeback acknowledged on %s",link.c_str());
|
||||
inhibit(*pend,0,SS7Layer2::Inactive);
|
||||
link << msg->params().getValue("pointcodetype") << "," << lbl;
|
||||
Debug(this,DebugNote,"Changeover order on %s",link.c_str());
|
||||
int seq = msg->params().getIntValue("sequence",-1);
|
||||
if (seq >= 0)
|
||||
recover(lbl,seq);
|
||||
// prepare an ECA in case we are unable to sena a COA/XCA
|
||||
static unsigned char data = SS7MsgSNM::ECA;
|
||||
return postpone(new SS7MSU(msu.getSIO(),lbl,&data,1),lbl,sls,0,200);
|
||||
}
|
||||
else
|
||||
Debug(this,DebugMild,"Unexpected %s %s [%p]",msg->name(),addr.c_str(),this);
|
||||
TelEngine::destruct(pend);
|
||||
}
|
||||
else if (msg->type() == SS7MsgSNM::COA ||
|
||||
msg->type() == SS7MsgSNM::XCA ||
|
||||
|
@ -484,6 +437,62 @@ HandledMSU SS7Management::receivedMSU(const SS7MSU& msu, const SS7Label& label,
|
|||
link << msg->params().getValue("pointcodetype") << "," << *pend;
|
||||
Debug(this,DebugNote,"Changeover acknowledged on %s",link.c_str());
|
||||
inhibit(*pend,SS7Layer2::Inactive);
|
||||
int seq = msg->params().getIntValue("sequence",-1);
|
||||
if (seq >= 0)
|
||||
recover(*pend,seq);
|
||||
}
|
||||
else
|
||||
Debug(this,DebugMild,"Unexpected %s %s [%p]",msg->name(),addr.c_str(),this);
|
||||
TelEngine::destruct(pend);
|
||||
}
|
||||
else if (msg->type() == SS7MsgSNM::CBD) {
|
||||
if (!len--)
|
||||
return false;
|
||||
const unsigned char* s = msu.getData(label.length()+2,len);
|
||||
if (!s)
|
||||
return false;
|
||||
Debug(this,DebugAll,"%s (code len=%u) [%p]",msg->name(),len,this);
|
||||
SS7Label lbl(label,label.sls(),0);
|
||||
if (inhibit(lbl,0,SS7Layer2::Inactive)) {
|
||||
String link;
|
||||
link << msg->params().getValue("pointcodetype") << "," << lbl;
|
||||
Debug(this,DebugNote,"Changeback declaration on %s",link.c_str());
|
||||
SS7MSU answer(msu.getSIO(),lbl,0,len+1);
|
||||
unsigned char* d = answer.getData(lbl.length()+1,len+1);
|
||||
if (!d)
|
||||
return false;
|
||||
*d++ = SS7MsgSNM::CBA;
|
||||
while (len--)
|
||||
*d++ = *s++;
|
||||
return transmitMSU(answer,lbl,sls) >= 0;
|
||||
}
|
||||
else
|
||||
Debug(this,DebugMild,"Unexpected %s %s [%p]",msg->name(),addr.c_str(),this);
|
||||
}
|
||||
else if (msg->type() == SS7MsgSNM::CBA) {
|
||||
if (!len--)
|
||||
return false;
|
||||
Debug(this,DebugAll,"%s (code len=%u) [%p]",msg->name(),len,this);
|
||||
lock();
|
||||
SnmPending* pend = 0;
|
||||
for (ObjList* l = m_pending.skipNull(); l; l = l->skipNext()) {
|
||||
SnmPending* p = static_cast<SnmPending*>(l->get());
|
||||
if (p->msu().length() != msu.length())
|
||||
continue;
|
||||
const unsigned char* ptr = p->msu().getData(p->length()+1,len+1);
|
||||
if (!ptr || (ptr[0] != SS7MsgSNM::CBD))
|
||||
continue;
|
||||
if (::memcmp(ptr+1,buf+1,len) || !p->matches(label))
|
||||
continue;
|
||||
pend = static_cast<SnmPending*>(m_pending.remove(p,false));
|
||||
break;
|
||||
}
|
||||
unlock();
|
||||
if (pend) {
|
||||
String link;
|
||||
link << msg->params().getValue("pointcodetype") << "," << *pend;
|
||||
Debug(this,DebugNote,"Changeback acknowledged on %s",link.c_str());
|
||||
inhibit(*pend,0,SS7Layer2::Inactive);
|
||||
}
|
||||
else
|
||||
Debug(this,DebugMild,"Unexpected %s %s [%p]",msg->name(),addr.c_str(),this);
|
||||
|
@ -506,6 +515,12 @@ HandledMSU SS7Management::receivedMSU(const SS7MSU& msu, const SS7Label& label,
|
|||
return transmitMSU(SS7MSU(msu.getSIO(),lbl,&lua,1),lbl,sls) >= 0;
|
||||
}
|
||||
}
|
||||
else if (msg->type() == SS7MsgSNM::UPU) {
|
||||
Debug(this,DebugNote,"Unavailable part %s at %s, cause %s",
|
||||
msg->params().getValue("part","?"),
|
||||
msg->params().getValue("destination","?"),
|
||||
msg->params().getValue("cause","?"));
|
||||
}
|
||||
else {
|
||||
String tmp;
|
||||
tmp.hexify((void*)buf,len,' ');
|
||||
|
@ -737,6 +752,7 @@ void SS7Management::notify(SS7Layer3* network, int sls)
|
|||
ctl->setParam("code",String(txSls));
|
||||
else {
|
||||
int seq = network->getSequence(sls);
|
||||
DDebug(this,DebugAll,"Got sequence number %d [%p]",seq,this);
|
||||
if (seq >= 0)
|
||||
ctl->setParam("sequence",String(seq));
|
||||
else
|
||||
|
@ -754,7 +770,7 @@ void SS7Management::notify(SS7Layer3* network, int sls)
|
|||
bool SS7Management::postpone(SS7MSU* msu, const SS7Label& label, int txSls,
|
||||
u_int64_t interval, u_int64_t global, const Time& when)
|
||||
{
|
||||
if (transmitMSU(*msu,label,txSls) >= 0) {
|
||||
if ((interval == 0) || transmitMSU(*msu,label,txSls) >= 0) {
|
||||
lock();
|
||||
m_pending.add(new SnmPending(msu,label,txSls,interval,global),when);
|
||||
unlock();
|
||||
|
@ -781,6 +797,10 @@ bool SS7Management::timeout(const SS7MSU& msu, const SS7Label& label, int txSls,
|
|||
Debug(this,DebugNote,"Changeover timed out on %s",link.c_str());
|
||||
inhibit(label,SS7Layer2::Inactive);
|
||||
break;
|
||||
case SS7MsgSNM::ECA:
|
||||
Debug(this,DebugNote,"Emergency changeover acknowledge on %s",link.c_str());
|
||||
transmitMSU(msu,label,txSls);
|
||||
break;
|
||||
case SS7MsgSNM::CBD:
|
||||
Debug(this,DebugNote,"Changeback timed out on %s",link.c_str());
|
||||
inhibit(label,0,SS7Layer2::Inactive);
|
||||
|
@ -826,6 +846,13 @@ bool SS7Management::inhibit(const SS7Label& link, int setFlags, int clrFlags)
|
|||
return router && router->inhibit(link,setFlags,clrFlags);
|
||||
}
|
||||
|
||||
void SS7Management::recover(const SS7Label& link, int sequence)
|
||||
{
|
||||
SS7Router* router = YOBJECT(SS7Router,SS7Layer4::network());
|
||||
if (router)
|
||||
router->recoverMSU(link,sequence);
|
||||
}
|
||||
|
||||
|
||||
HandledMSU SS7Maintenance::receivedMSU(const SS7MSU& msu, const SS7Label& label, SS7Layer3* network, int sls)
|
||||
{
|
||||
|
|
|
@ -806,6 +806,40 @@ bool SS7Router::inhibit(const SS7Label& link, int setFlags, int clrFlags, bool n
|
|||
return false;
|
||||
}
|
||||
|
||||
int SS7Router::getSequence(const SS7Label& link)
|
||||
{
|
||||
int remote = link.dpc().pack(link.type());
|
||||
if (!remote)
|
||||
return false;
|
||||
Lock mylock(this);
|
||||
for (ObjList* o = m_layer3.skipNull(); o; o = o->skipNext()) {
|
||||
L3Pointer* p = static_cast<L3Pointer*>(o->get());
|
||||
if (!*p || (*p)->getRoutePriority(link.type(),remote))
|
||||
continue;
|
||||
RefPointer<SS7Layer3> net = static_cast<SS7Layer3*>(*p);
|
||||
mylock.drop();
|
||||
return net->getSequence(link.sls());
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void SS7Router::recoverMSU(const SS7Label& link, int sequence)
|
||||
{
|
||||
int remote = link.dpc().pack(link.type());
|
||||
if (!remote)
|
||||
return;
|
||||
Lock mylock(this);
|
||||
for (ObjList* o = m_layer3.skipNull(); o; o = o->skipNext()) {
|
||||
L3Pointer* p = static_cast<L3Pointer*>(o->get());
|
||||
if (!*p || (*p)->getRoutePriority(link.type(),remote))
|
||||
continue;
|
||||
RefPointer<SS7Layer3> net = static_cast<SS7Layer3*>(*p);
|
||||
mylock.drop();
|
||||
net->recoverMSU(link.sls(),sequence);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SS7Router::notify(SS7Layer3* network, int sls)
|
||||
{
|
||||
DDebug(this,DebugInfo,"Notified %s on %p sls %d [%p]",
|
||||
|
|
|
@ -1295,23 +1295,28 @@ bool SS7M2PA::processLinkStatus(DataBlock& data,int streamId)
|
|||
return true;
|
||||
}
|
||||
|
||||
ObjList* SS7M2PA::recoverMSU()
|
||||
void SS7M2PA::recoverMSU(int sequence)
|
||||
{
|
||||
Lock lock(m_mutex);
|
||||
ObjList* lst = 0;
|
||||
for (;;) {
|
||||
m_mutex.lock();
|
||||
DataBlock* pkt = static_cast<DataBlock*>(m_ackList.remove(false));
|
||||
m_mutex.unlock();
|
||||
if (!pkt)
|
||||
break;
|
||||
if (pkt->length() > 8) {
|
||||
SS7MSU* msu = new SS7MSU(8 + (char*)pkt->data(),pkt->length() - 8);
|
||||
if (!lst)
|
||||
lst = new ObjList;
|
||||
lst->append(msu);
|
||||
unsigned char* head = pkt->data(0,8);
|
||||
if (head) {
|
||||
int seq = head[7] | ((int)head[6] << 8) | ((int)head[5] << 16);
|
||||
if (sequence < 0 || ((seq - sequence) & 0x00ffffff) < 0x007fffff) {
|
||||
sequence = -1;
|
||||
SS7MSU msu(head + 8,pkt->length() - 8);
|
||||
recoveredMSU(msu);
|
||||
}
|
||||
else
|
||||
Debug(this,DebugAll,"Not recovering MSU with seq=%d, requested %d",
|
||||
seq,sequence);
|
||||
}
|
||||
TelEngine::destruct(pkt);
|
||||
}
|
||||
return lst;
|
||||
}
|
||||
|
||||
void SS7M2PA::retransData()
|
||||
|
@ -1423,7 +1428,7 @@ bool SS7M2UAClient::processMSG(unsigned char msgVersion, unsigned char msgClass,
|
|||
case 4: // Release Request
|
||||
case 7: // State Request
|
||||
case 10: // Data Retrieval Request
|
||||
Debug(this,DebugWarn,"Received M2UA SG request %u on APS side!",msgType);
|
||||
Debug(this,DebugWarn,"Received M2UA SG request %u on ASP side!",msgType);
|
||||
return false;
|
||||
}
|
||||
getTag(msg,0x0001,iid);
|
||||
|
@ -1443,9 +1448,11 @@ bool SS7M2UAClient::processMSG(unsigned char msgVersion, unsigned char msgClass,
|
|||
|
||||
SS7M2UA::SS7M2UA(const NamedList& params)
|
||||
: SignallingComponent(params.safe("SS7M2UA"),¶ms),
|
||||
m_retrieve(50),
|
||||
m_iid(params.getIntValue("iid",-1)), m_linkState(LinkDown), m_rpo(false)
|
||||
{
|
||||
Debug(DebugStub,"SS7M2UA");
|
||||
m_retrieve.interval(params,"retrieve",5,200,true);
|
||||
}
|
||||
|
||||
bool SS7M2UA::initialize(const NamedList* config)
|
||||
|
@ -1496,20 +1503,23 @@ bool SS7M2UA::control(Operation oper, NamedList* params)
|
|||
}
|
||||
switch (oper) {
|
||||
case Pause:
|
||||
m_linkState = LinkDown;
|
||||
SS7Layer2::notify();
|
||||
if (aspActive()) {
|
||||
DataBlock buf;
|
||||
if (m_iid >= 0)
|
||||
SIGAdaptation::addTag(buf,0x0001,(u_int32_t)m_iid);
|
||||
// Release Request
|
||||
return adaptation()->transmitMSG(SIGTRAN::MAUP,4,buf,1);
|
||||
if (!adaptation()->transmitMSG(SIGTRAN::MAUP,4,buf,1))
|
||||
return false;
|
||||
getSequence();
|
||||
}
|
||||
m_linkState = LinkDown;
|
||||
if (!m_retrieve.started())
|
||||
SS7Layer2::notify();
|
||||
return true;
|
||||
case Resume:
|
||||
if (operational())
|
||||
return true;
|
||||
if (!m_autostart)
|
||||
if (!m_autostart || m_retrieve.started())
|
||||
return activate();
|
||||
// fall through
|
||||
case Align:
|
||||
|
@ -1561,6 +1571,51 @@ bool SS7M2UA::transmitMSU(const SS7MSU& msu)
|
|||
return adaptation()->transmitMSG(SIGTRAN::MAUP,1,buf,1);
|
||||
}
|
||||
|
||||
void SS7M2UA::recoverMSU(int sequence)
|
||||
{
|
||||
Lock mylock(adaptation());
|
||||
if (sequence >= 0 && aspUp() && transport()) {
|
||||
Debug(this,DebugInfo,"Retrieving MSUs from sequence %d from M2UA SG",sequence);
|
||||
DataBlock buf;
|
||||
if (m_iid >= 0)
|
||||
SIGAdaptation::addTag(buf,0x0001,(u_int32_t)m_iid);
|
||||
// Retrieve MSGS action
|
||||
SIGAdaptation::addTag(buf,0x0306,(u_int32_t)0);
|
||||
SIGAdaptation::addTag(buf,0x0307,(u_int32_t)sequence);
|
||||
// Data Retrieval Request
|
||||
adaptation()->transmitMSG(SIGTRAN::MAUP,10,buf,1);
|
||||
}
|
||||
}
|
||||
|
||||
int SS7M2UA::getSequence()
|
||||
{
|
||||
if (m_lastSeqRx == -1) {
|
||||
m_lastSeqRx = -2;
|
||||
Lock mylock(adaptation());
|
||||
if (aspUp() && transport()) {
|
||||
Debug(this,DebugInfo,"Requesting sequence number from M2UA SG");
|
||||
DataBlock buf;
|
||||
if (m_iid >= 0)
|
||||
SIGAdaptation::addTag(buf,0x0001,(u_int32_t)m_iid);
|
||||
// Retrieve BSN action
|
||||
SIGAdaptation::addTag(buf,0x0306,(u_int32_t)1);
|
||||
// Data Retrieval Request
|
||||
if (adaptation()->transmitMSG(SIGTRAN::MAUP,10,buf,1))
|
||||
m_retrieve.start();
|
||||
}
|
||||
}
|
||||
return m_lastSeqRx;
|
||||
}
|
||||
|
||||
void SS7M2UA::timerTick(const Time& when)
|
||||
{
|
||||
if (m_retrieve.timeout(when.msec())) {
|
||||
m_retrieve.stop();
|
||||
SS7Layer2::notify();
|
||||
control(Resume);
|
||||
}
|
||||
}
|
||||
|
||||
bool SS7M2UA::processMGMT(unsigned char msgType, const DataBlock& msg, int streamId)
|
||||
{
|
||||
const char* err = "Unhandled";
|
||||
|
@ -1603,12 +1658,13 @@ bool SS7M2UA::processMAUP(unsigned char msgType, const DataBlock& msg, int strea
|
|||
// Correlation ID present, send Data Ack
|
||||
DataBlock buf;
|
||||
SIGAdaptation::addTag(buf,0x0013,corrId);
|
||||
adaptation()->transmitMSG(SIGTRAN::MAUP,0x15,buf,streamId);
|
||||
adaptation()->transmitMSG(SIGTRAN::MAUP,15,buf,streamId);
|
||||
}
|
||||
return receivedMSU(data);
|
||||
}
|
||||
break;
|
||||
case 3: // Establish Confirm
|
||||
m_lastSeqRx = -1;
|
||||
m_linkState = LinkUp;
|
||||
m_rpo = false;
|
||||
SS7Layer2::notify();
|
||||
|
@ -1642,6 +1698,53 @@ bool SS7M2UA::processMAUP(unsigned char msgType, const DataBlock& msg, int strea
|
|||
SS7Layer2::notify();
|
||||
}
|
||||
return true;
|
||||
case 11: // Data Retrieval Confirm
|
||||
{
|
||||
u_int32_t res = 0;
|
||||
if (!SIGAdaptation::getTag(msg,0x0308,res)) {
|
||||
err = "Missing retrieval result";
|
||||
break;
|
||||
}
|
||||
if (res) {
|
||||
err = "Retrieval failed";
|
||||
break;
|
||||
}
|
||||
if (SIGAdaptation::getTag(msg,0x0306,res) && (res == 1)) {
|
||||
// Action was BSN retrieval
|
||||
res = (u_int32_t)-1;
|
||||
if (!SIGAdaptation::getTag(msg,0x0307,res)) {
|
||||
err = "Missing BSN field in retrieval";
|
||||
if (m_retrieve.started()) {
|
||||
m_retrieve.stop();
|
||||
SS7Layer2::notify();
|
||||
}
|
||||
break;
|
||||
}
|
||||
Debug(this,DebugInfo,"Recovered sequence number %u",res);
|
||||
if (res & 0xffffff80)
|
||||
res = (res & 0x00ffffff) | 0x01000000;
|
||||
m_lastSeqRx = res;
|
||||
if (m_retrieve.started()) {
|
||||
m_retrieve.stop();
|
||||
SS7Layer2::notify();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 12: // Data Retrieval Indication
|
||||
case 13: // Data Retrieval Complete Indication
|
||||
{
|
||||
SS7MSU data;
|
||||
if (!SIGAdaptation::getTag(msg,0x0300,data)) {
|
||||
if (msgType == 13)
|
||||
return true;
|
||||
err = "Missing data in";
|
||||
break;
|
||||
}
|
||||
return recoveredMSU(data);
|
||||
}
|
||||
break;
|
||||
}
|
||||
Debug(this,DebugStub,"%s M2UA MAUP message type %u",err,msgType);
|
||||
return false;
|
||||
|
@ -1650,15 +1753,18 @@ bool SS7M2UA::processMAUP(unsigned char msgType, const DataBlock& msg, int strea
|
|||
void SS7M2UA::activeChange(bool active)
|
||||
{
|
||||
if (!active) {
|
||||
getSequence();
|
||||
m_rpo = false;
|
||||
switch (m_linkState) {
|
||||
case LinkUpEmg:
|
||||
m_linkState = LinkReqEmg;
|
||||
SS7Layer2::notify();
|
||||
if (!m_retrieve.started())
|
||||
SS7Layer2::notify();
|
||||
break;
|
||||
case LinkUp:
|
||||
m_linkState = LinkReq;
|
||||
SS7Layer2::notify();
|
||||
if (!m_retrieve.started())
|
||||
SS7Layer2::notify();
|
||||
break;
|
||||
case LinkReqEmg:
|
||||
case LinkReq:
|
||||
|
@ -1700,7 +1806,7 @@ bool ISDNIUAClient::processMSG(unsigned char msgVersion, unsigned char msgClass,
|
|||
case 3: // Unit Data Request Message
|
||||
case 5: // Establish Request
|
||||
case 8: // Release Request
|
||||
Debug(this,DebugWarn,"Received IUA SG request %u on APS side!",msgType);
|
||||
Debug(this,DebugWarn,"Received IUA SG request %u on ASP side!",msgType);
|
||||
return false;
|
||||
}
|
||||
getTag(msg,0x0001,iid);
|
||||
|
|
|
@ -4926,6 +4926,15 @@ protected:
|
|||
*/
|
||||
virtual bool receivedMSU(const SS7MSU& msu, SS7Layer2* link, int sls) = 0;
|
||||
|
||||
/**
|
||||
* Process a MSU recovered from the Layer 2 component after failure
|
||||
* @param msu Message data, starting with Service Indicator Octet
|
||||
* @param link Data link from where the MSU was recovered
|
||||
* @param sls Signalling Link the MSU was recovered from
|
||||
* @return True if the MSU was processed
|
||||
*/
|
||||
virtual bool recoveredMSU(const SS7MSU& msu, SS7Layer2* link, int sls) = 0;
|
||||
|
||||
/**
|
||||
* Process a notification generated by the attached data link
|
||||
* @param link Data link that generated the notification
|
||||
|
@ -4999,9 +5008,10 @@ public:
|
|||
|
||||
/**
|
||||
* Remove the MSUs waiting in the transmit queue and return them
|
||||
* @return List of MSUs taken from the queue
|
||||
* @param sequence First sequence number to recover, flush earlier packets
|
||||
*/
|
||||
virtual ObjList* recoverMSU();
|
||||
virtual void recoverMSU(int sequence)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Retrieve the current link status indications
|
||||
|
@ -5077,7 +5087,7 @@ public:
|
|||
* Get the sequence number of the last MSU received
|
||||
* @return Last FSN received, negative if not available
|
||||
*/
|
||||
virtual int getSequence() const
|
||||
virtual int getSequence()
|
||||
{ return m_lastSeqRx; }
|
||||
|
||||
/**
|
||||
|
@ -5120,6 +5130,19 @@ protected:
|
|||
return tmp && tmp->receivedMSU(msu,this,m_sls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Push a recovered Message Signal Unit back up the protocol stack
|
||||
* @param msu Message data, starting with Service Indicator Octet
|
||||
* @return True if message was successfully delivered to the user component
|
||||
*/
|
||||
inline bool recoveredMSU(const SS7MSU& msu)
|
||||
{
|
||||
m_l2userMutex.lock();
|
||||
RefPointer<SS7L2User> tmp = m_l2user;
|
||||
m_l2userMutex.unlock();
|
||||
return tmp && tmp->recoveredMSU(msu,this,m_sls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify out user part about a status change
|
||||
*/
|
||||
|
@ -5337,6 +5360,17 @@ protected:
|
|||
*/
|
||||
virtual HandledMSU receivedMSU(const SS7MSU& msu, const SS7Label& label, SS7Layer3* network, int sls) = 0;
|
||||
|
||||
/**
|
||||
* Reroute a recovered Message Signal Unit
|
||||
* @param msu Message data, starting with Service Indicator Octet
|
||||
* @param label Routing label of the recovered MSU
|
||||
* @param network Network layer that recovered the MSU
|
||||
* @param sls Signalling Link the MSU was recovered from
|
||||
* @return True if the MSU was successfully rerouted
|
||||
*/
|
||||
virtual bool recoveredMSU(const SS7MSU& msu, const SS7Label& label, SS7Layer3* network, int sls)
|
||||
{ return false; }
|
||||
|
||||
/**
|
||||
* Process a notification generated by the attached network layer
|
||||
* @param link Network or linkset that generated the notification
|
||||
|
@ -5426,6 +5460,14 @@ public:
|
|||
virtual int getSequence(int sls) const
|
||||
{ return -1; }
|
||||
|
||||
/**
|
||||
* Remove the MSUs waiting in the transmit queue and return them
|
||||
* @param sls Signalling Link to recover MSUs from
|
||||
* @param sequence First sequence number to recover, flush earlier packets
|
||||
*/
|
||||
virtual void recoverMSU(int sls, int sequence)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Initiate a MTP restart procedure if supported by the network layer
|
||||
* @return True if a restart was initiated
|
||||
|
@ -5594,6 +5636,21 @@ protected:
|
|||
return tmp ? tmp->receivedMSU(msu,label,this,sls) : HandledMSU(HandledMSU::Unequipped);
|
||||
}
|
||||
|
||||
/**
|
||||
* Push a recovered Message Signal Unit back up the protocol stack
|
||||
* @param msu Message data, starting with Service Indicator Octet
|
||||
* @param label Routing label of the recovered MSU
|
||||
* @param sls Signalling Link the MSU was recovered from
|
||||
* @return True if the MSU was successfully rerouted
|
||||
*/
|
||||
inline bool recoveredMSU(const SS7MSU& msu, const SS7Label& label, int sls)
|
||||
{
|
||||
m_l3userMutex.lock();
|
||||
RefPointer<SS7L3User> tmp = m_l3user;
|
||||
m_l3userMutex.unlock();
|
||||
return tmp && tmp->recoveredMSU(msu,label,this,sls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify out user part about a status change
|
||||
* @param sls Signallink Link that generated the notification, -1 if none
|
||||
|
@ -5937,6 +5994,20 @@ public:
|
|||
*/
|
||||
bool inhibit(const SS7Label& link, int setFlags, int clrFlags = 0, bool notLast = false);
|
||||
|
||||
/**
|
||||
* Get the sequence number of the last MSU received on a link
|
||||
* @param link Routing label identifying the link to retrieve the sequence from
|
||||
* @return Last FSN received, negative if not available
|
||||
*/
|
||||
int getSequence(const SS7Label& link);
|
||||
|
||||
/**
|
||||
* Remove the MSUs waiting in the transmit queue and return them
|
||||
* @param link Routing label identifying the link to recover MSUs
|
||||
* @param sequence First sequence number to recover, flush earlier packets
|
||||
*/
|
||||
void recoverMSU(const SS7Label& link, int sequence);
|
||||
|
||||
/**
|
||||
* Check if the transfer function is enabled
|
||||
* @return True if acting as a STP
|
||||
|
@ -6110,19 +6181,19 @@ public:
|
|||
* @param msu MSU data to transmit
|
||||
* @return True if message was successfully queued
|
||||
*/
|
||||
virtual bool transmitMSU(const SS7MSU& msu);
|
||||
virtual bool transmitMSU(const SS7MSU& msu);
|
||||
|
||||
/**
|
||||
* Method called when the transport status has been changed
|
||||
* @param status Up or down
|
||||
*/
|
||||
virtual void notifyLayer(SignallingInterface::Notification status);
|
||||
virtual void notifyLayer(SignallingInterface::Notification status);
|
||||
|
||||
/**
|
||||
* Remove the MSUs waiting in the transmit queue and return them
|
||||
* @return List of MSUs taken from the queue
|
||||
* @param sequence First sequence number to recover, flush earlier packets
|
||||
*/
|
||||
virtual ObjList* recoverMSU();
|
||||
virtual void recoverMSU(int sequence);
|
||||
|
||||
/**
|
||||
* Decode sequence numbers from message and process them
|
||||
|
@ -6326,12 +6397,24 @@ public:
|
|||
*/
|
||||
virtual bool transmitMSU(const SS7MSU& msu);
|
||||
|
||||
/**
|
||||
* Remove the MSUs waiting in the transmit queue and return them
|
||||
* @param sequence First sequence number to recover, flush earlier packets
|
||||
*/
|
||||
virtual void recoverMSU(int sequence);
|
||||
|
||||
/**
|
||||
* Check if the link is fully operational
|
||||
* @return True if the link is aligned and operational
|
||||
*/
|
||||
virtual bool operational() const;
|
||||
|
||||
/**
|
||||
* Get the sequence number of the last MSU received, request if not available
|
||||
* @return Last FSN received, negative if not available
|
||||
*/
|
||||
virtual int getSequence();
|
||||
|
||||
/**
|
||||
* Traffic activity state change notification
|
||||
* @param active True if the ASP is active and traffic is allowed
|
||||
|
@ -6353,10 +6436,18 @@ protected:
|
|||
LinkUp,
|
||||
LinkUpEmg,
|
||||
};
|
||||
|
||||
/**
|
||||
* Periodical timer tick used to perform alignment and housekeeping
|
||||
* @param when Time to use as computing base for events and timeouts
|
||||
*/
|
||||
virtual void timerTick(const Time& when);
|
||||
|
||||
SS7M2UAClient* client() const
|
||||
{ return static_cast<SS7M2UAClient*>(adaptation()); }
|
||||
virtual bool processMGMT(unsigned char msgType, const DataBlock& msg, int streamId);
|
||||
virtual bool processMAUP(unsigned char msgType, const DataBlock& msg, int streamId);
|
||||
SignallingTimer m_retrieve;
|
||||
int32_t m_iid;
|
||||
int m_linkState;
|
||||
bool m_rpo;
|
||||
|
@ -6418,9 +6509,9 @@ public:
|
|||
|
||||
/**
|
||||
* Remove the MSUs waiting in the transmit queue and return them
|
||||
* @return List of MSUs taken from the queue
|
||||
* @param sequence First sequence number to recover, flush earlier packets
|
||||
*/
|
||||
virtual ObjList* recoverMSU();
|
||||
virtual void recoverMSU(int sequence);
|
||||
|
||||
/**
|
||||
* Retrieve the current link status indications
|
||||
|
@ -6651,6 +6742,13 @@ public:
|
|||
*/
|
||||
virtual int getSequence(int sls) const;
|
||||
|
||||
/**
|
||||
* Remove the MSUs waiting in the transmit queue and return them
|
||||
* @param sls Signalling Link to recover MSUs from
|
||||
* @param sequence First sequence number to recover, flush earlier packets
|
||||
*/
|
||||
virtual void recoverMSU(int sls, int sequence);
|
||||
|
||||
/**
|
||||
* Execute a control operation on the linkset
|
||||
* @param oper Operation to execute
|
||||
|
@ -6714,6 +6812,15 @@ protected:
|
|||
*/
|
||||
virtual bool receivedMSU(const SS7MSU& msu, SS7Layer2* link, int sls);
|
||||
|
||||
/**
|
||||
* Process a MSU recovered from the Layer 2 component after failure
|
||||
* @param msu Message data, starting with Service Indicator Octet
|
||||
* @param link Data link from where the MSU was recovered
|
||||
* @param sls Signalling Link the MSU was recovered from
|
||||
* @return True if the MSU was processed
|
||||
*/
|
||||
virtual bool recoveredMSU(const SS7MSU& msu, SS7Layer2* link, int sls);
|
||||
|
||||
/**
|
||||
* Process a notification generated by the attached data link
|
||||
* @param link Data link that generated the notification
|
||||
|
@ -7226,6 +7333,13 @@ protected:
|
|||
*/
|
||||
bool inhibit(const SS7Label& link, int setFlags, int clrFlags = 0);
|
||||
|
||||
/**
|
||||
* Recover MSUs from a link
|
||||
* @param link Signalling Link to recover identified by a routing label
|
||||
* @param sequence Starting sequence number to recover
|
||||
*/
|
||||
void recover(const SS7Label& link, int sequence);
|
||||
|
||||
/**
|
||||
* Process a notification generated by the attached network layer
|
||||
* @param link Network or linkset that generated the notification
|
||||
|
|
Loading…
Reference in New Issue