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:
paulc 2010-08-29 18:14:52 +00:00
parent b0d3f6c656
commit 11419dded4
6 changed files with 426 additions and 100 deletions

View File

@ -214,11 +214,6 @@ bool SS7Layer2::control(NamedList& params)
return (cmd >= 0) && control((Operation)cmd,&params);
}
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

View File

@ -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);

View File

@ -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)
{

View File

@ -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]",

View File

@ -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"),&params),
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);

View File

@ -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