Notify SCCP about subsystem management status changes for TCAP.

git-svn-id: http://yate.null.ro/svn/yate/trunk@5290 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
oana 2012-10-02 14:33:43 +00:00
parent cb0d669c39
commit d8fe81ac8f
3 changed files with 99 additions and 2 deletions

View File

@ -53,6 +53,10 @@ void TCAPUser::destroyed()
Debug(this,DebugAll,"TCAPUser::destroyed() [%p]",this);
Lock lock(m_tcapMtx);
if (m_tcap) {
// notify SCCP OutOfService
NamedList p("");
m_tcap->updateUserStatus(this,SCCPManagement::UserOutOfService,p);
m_tcap->detach(this);
Debug(this,DebugAll,"TCAPUser::~TCAPUser() [%p] - Detached from TCAP (%p,%s)",this,m_tcap,m_tcap->toString().safe());
m_tcap->deref();
@ -269,6 +273,7 @@ SS7TCAP::SS7TCAP(const NamedList& params)
{
Debug(this,DebugAll,"SS7TCAP::SS7TCAP() [%p] created",this);
m_recvMsgs = m_sentMsgs = m_discardMsgs = m_normalMsgs = m_abnormalMsgs = 0;
m_ssnStatus = SCCPManagement::UserOutOfService;
}
SS7TCAP::~SS7TCAP()
@ -322,7 +327,13 @@ bool SS7TCAP::initialize(const NamedList* config)
s_printMsgs = config->getBoolValue(YSTRING("print-messages"),false);
s_extendedDbg = config->getBoolValue(YSTRING("extended-debug"),false);
}
return SCCPUser::initialize(config);
bool ok = SCCPUser::initialize(config);
if (ok) {
NamedList p("");
sendSCCPNotify(p);
Debug(this,DebugInfo,"SSN=%d has status='%s'[%p]",m_SSN,lookup(m_ssnStatus,SCCPManagement::broadcastType(),""),this);
}
return ok;
}
bool SS7TCAP::sendData(DataBlock& data, NamedList& params)
@ -408,6 +419,56 @@ bool SS7TCAP::managementNotify(SCCP::Type type, NamedList& params)
return ok;
}
void SS7TCAP::updateUserStatus(TCAPUser* user, SCCPManagement::LocalBroadcast status, NamedList& params)
{
if (!user)
return;
DDebug(this,DebugAll,"SS7TCAP::updateUserStatus(user=%s[%p],status=%d) [%p]",user->toString().c_str(),user,status,this);
bool notify = false;
Lock l(m_usersMtx);
SCCPManagement::LocalBroadcast tmp = m_ssnStatus;
switch (m_ssnStatus) {
case SCCPManagement::UserOutOfService:
if (status == SCCPManagement::UserInService) {
m_ssnStatus = SCCPManagement::UserInService;
notify = true;
}
break;
case SCCPManagement::UserInService:
if (status == SCCPManagement::UserOutOfService) {
ListIterator it(m_users);
for (;;) {
TCAPUser* usr = static_cast<TCAPUser*>(it.get());
// End of iteration?
if (!usr) {
m_ssnStatus = SCCPManagement::UserOutOfService;
notify = true;
break;
}
if (usr->managementState() == (int) SCCPManagement::UserInService)
break;
}
}
default:
break;
}
if (notify) {
sendSCCPNotify(params); // it always returns false, so no point in checking result
Debug(this,DebugInfo,"SSN=%d changed status from '%s' to '%s' [%p]",m_SSN,
lookup(tmp,SCCPManagement::broadcastType(),""),lookup(m_ssnStatus,SCCPManagement::broadcastType(),""),this);
}
}
bool SS7TCAP::sendSCCPNotify(NamedList& params)
{
params.setParam(YSTRING("subsystem-status"),lookup(m_ssnStatus,SCCPManagement::broadcastType(),""));
params.setParam(YSTRING("ssn"),String(m_SSN));
if (!params.getParam(YSTRING("smi")))
params.setParam("smi","0");
return sccpNotify(SCCP::StatusRequest,params);
}
void SS7TCAP::attach(TCAPUser* user)
{
if (!user)

View File

@ -10862,6 +10862,14 @@ public:
*/
virtual HandledMSU handleError(SS7TCAPError& error, NamedList& params, DataBlock& data, SS7TCAPTransaction* tr = 0);
/**
* Update the SCCP Management state for this SSN when requested by a user
* @param user The TCAP user which changed its state
* @param status The state of the TCAP user
* @param params Additional parameters to be transmitted to the SCPP
*/
virtual void updateUserStatus(TCAPUser* user, SCCPManagement::LocalBroadcast status, NamedList& params);
/**
* Increment one of the status counters
* @param counterType The type of the counter to increment
@ -10948,6 +10956,7 @@ public:
protected:
virtual SS7TCAPError decodeTransactionPart(NamedList& params, DataBlock& data) = 0;
virtual void encodeTransactionPart(NamedList& params, DataBlock& data) = 0;
bool sendSCCPNotify(NamedList& params);
// list of TCAP users attached to this TCAP instance
ObjList m_users;
Mutex m_usersMtx;
@ -10978,6 +10987,9 @@ protected:
unsigned int m_discardMsgs;
unsigned int m_normalMsgs;
unsigned int m_abnormalMsgs;
// Subsystem Status
SCCPManagement::LocalBroadcast m_ssnStatus;
};
class YSIG_API SS7TCAPError

View File

@ -233,6 +233,7 @@ public:
virtual bool managementNotify(SCCP::Type type, NamedList& params);
bool findTCAP(const char* name);
int managementState();
void notifyManagementState(bool forced = false);
bool initialize(NamedList& sect);
bool createApplication(Socket* skt, String& addr);
void setListener(XMLConnListener* list);
@ -261,6 +262,7 @@ protected:
UserType m_type;
bool m_printMsg;
bool m_addEnc;
SCCPManagement::LocalBroadcast m_mngtStatus;
};
class TcapXApplication : public RefObject, public Mutex
@ -8335,6 +8337,7 @@ void TcapXApplication::reportState(State state, const char* error)
break;
case Active:
sendStateResponse();
m_user->notifyManagementState();
break;
case ShutDown:
Debug(&__plugin,DebugInfo,"Requested shutdown, %d transactions pending [%p]",trCount(),this);
@ -8414,7 +8417,8 @@ TcapXUser::TcapXUser(const char* name)
Mutex(true,name),
m_appsMtx(true,"TCAPXApps"),
m_listener(0), m_type(MAP),
m_printMsg(false), m_addEnc(false)
m_printMsg(false), m_addEnc(false),
m_mngtStatus(SCCPManagement::UserOutOfService)
{
Debug(&__plugin,DebugAll,"TcapXUser '%s' created [%p]",toString().c_str(),this);
}
@ -8469,6 +8473,7 @@ bool TcapXUser::initialize(NamedList& sect)
m_addEnc = sect.getBoolValue("add-encoding",false);
if (!tcap() && !findTCAP(sect.getValue("tcap",0)))
return false;
notifyManagementState(true);
return true;
}
@ -8477,6 +8482,8 @@ void TcapXUser::removeApp(TcapXApplication* app)
Debug(this,DebugAll,"Removing application=%s[%p] [%p]",(app ? app->toString().c_str() : ""),app,this);
Lock l(m_appsMtx);
m_apps.remove(app);
l.drop();
notifyManagementState();
}
bool TcapXUser::tcapIndication(NamedList& params)
@ -8694,6 +8701,23 @@ int TcapXUser::managementState()
return SCCPManagement::UserOutOfService;
}
void TcapXUser::notifyManagementState(bool forced)
{
DDebug(this,DebugAll,"TcapXUser::notifyManagementState(forced=%s) [%p]",String::boolText(forced),this);
SCCPManagement::LocalBroadcast state = (SCCPManagement::LocalBroadcast)managementState();
Lock l(this);
if (forced || state != m_mngtStatus) {
Debug(this,DebugInfo,"Changing management state from '%s' to '%s' [%p]",
lookup(m_mngtStatus,SCCPManagement::broadcastType(),""),lookup(state,SCCPManagement::broadcastType(),""),this);
m_mngtStatus = state;
l.drop();
if (tcap()) {
NamedList p("");
tcap()->updateUserStatus(this,state,p);
}
}
}
void TcapXUser::setListener(XMLConnListener* list)
{
Lock l(this);