Added SCCP support.

git-svn-id: http://voip.null.ro/svn/yate@4590 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
andrei 2011-09-09 12:43:59 +00:00
parent 9a85d0facd
commit 7f5e2e5e88
4 changed files with 6828 additions and 18 deletions

View File

@ -684,3 +684,132 @@
; neighbours: boolean: Only accept management messages from adjacent nodes
;neighbours=yes
; Example of a SS7 SCCP
;[sccp]
; type: keyword: identifies the component as a SS7 SCCP
; type=ss7-sccp
; pointcodetype: string: SS7 point code type (required)
; Allowed values:
; ITU ITU-T Q.704
; ANSI ANSI T1.111.4
;pointcodetype=
; localpointcode: string: Local point code to accept as destination (required)
; The format is network-cluster-member or number
;localpointcode=
; router: string: Name of the SS7 Router to attach to
; A boolean false value disables attaching a router (unlikely)
;router=ss7router
; network: string: Name of linkset to attach to if router is disabled
; This allows direct connection without MTP management (unlikely)
;network=
; management : string: Name of the SS7 management to use
;management=sccp-mgm
; hopcounter : integer: Default value for hop-counter
; This value indicates the maximum number of gt translations that can be made before
; the message reach it's destination
;hopcounter=15
; ludt-support : boolean: True to allow sccp to send Long UnitData messages
;ludt-support=false
; segmentation-timeout: integer: Time in milliseconds before a segmented message is expired
; Values: 5000-20000 ms
;segmentation-timeout=5000
; extended-monitoring : boolean: Compute an extended monitoring of sccp messages
;extended-monitoring=no
; print-messages: boolean: Print decoded protocol data units to output
; This option is applied on reload
; Defaults to no
;print-messages=no
; extended-debug: boolean: Print extended debug data (such as raw hex data) to output
; This option is applied on reload
; Defaults to no
;extended-debug=no
; endpoint: boolean : Force message processing if we are an endpoint
; This option will allow sccp to process failed gt translations messages if a ssn is pressent
;endpoint=true;
; Example of SS7 Sccp Management
;[sccp-mgm]
; type: keyword: identifies the component as a SS7 SCCP Management
; Values : ss7-sccp-itu-mgm
; Must correspond with the pointcode type of the sccp
;type=
; test-timer : integer: Initial time in milliseconds for Subsystem Status Test to be generated
; Values : 5000-10000
; Note! This timer will increase exponentially until reaches 20000 if no corresponding message is received
; from the test initiator
;test-timer=5000
; print-messages : boolean: True to print sccp management messages
;print-messages=false
; remote : struct: Remote SCCP witch present interest for GTT (Global Title Translator)
; This parameter allow us to monitor remote sccp's state
; This option can be repeated to monitor multiple remote sccp's
; Format: remote=pc(integer):ssn1,ssn2,....
; pc : integer: Remote sccp pointcode
; ssn1 - ssnn: integer; Remote sccp subsystems witch we are monitoring
; Note! Ssn list may be empty if the remote sccp is a stp with GTT
;remote=2057:1,2,3,4
; concerned : struct: List of remote sccp's witch are concerned about local state
; This parameter allow us to inform remote sccp's when local status has changed
; This option can be repeated to inform multiple remote sccp's
; Format: remote=pc(integer):ssn1,ssn2,....
; pc : integer: Remote sccp pointcode
; ssn1 - ssnn: integer; List of local subsystems witch are of interest for the remote sccp
; Note! Ssn list may be empty if the remote sccp is concerned only if local sccp is available or not
;concerned=2057:1,2,3,4
; local-subsystems : string: Coma separated list of local subsystems
; The subsystems present in this list will be monitored by this sccp management
;local-subsystems=1,2,3,4,5,..
; auto-monitor: boolean: True to auto monitor remote sccp's.
; This flag enables remote sccp auto monitoring. When a message failed to be send to a remote sccp,
; the sccp management will automaticaly append the destination to the monitored remote sccp destinations
; to prevent sccp routing failure.
; NOTE! Do not use this option if your GTT (Global Title Translator) can route to a large number of remote addresses
; because a lot of memory and cpu power will be used!
;auto-monitor=false
; Example of GTT (Global Title Translator)
;[gtt]
; type : keyword: Identifies this component as a GTT
; NOTE! This type of gtt is based on yate messages system.
;type=ss7-gtt
; sccp : string: The name of the sccp to attach to this GTT
;sccp=sccp
; Example of dummy sccp user
;[sccp-userd]
; Sccp user dummy sends a message over sccp protocol.
; type : keyword: Identifies this component as a Sccp User Dummy
type=ss7-sccpu-dummy
; sccp : string: The name of the sccp to attach to this Sccp User
;sccp=sccp
; ssn : integer: Optional ssn asociated with this user
; If this parameter is present this user will accept only the messages who have the same ssn
;ssn=0

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -33,6 +33,7 @@ namespace { // anonymous
class SigChannel; // Signalling channel
class SigDriver; // Signalling driver
class SigTopmost; // Keep a topmost non-trunk component
class OnDemand; // On demand component
class SigCircuitGroup; // Used to create a signalling circuit group descendant to set the debug name
class SigTrunk; // Keep a signalling trunk
class SigSS7Isup; // SS7 ISDN User Part call controller
@ -159,6 +160,7 @@ class SigDriver : public Driver
{
friend class SigTopmost;
friend class SigTrunk; // Needded for appendTrunk() / removeTrunk()
friend class OnDemand; // Needed for Append OnDemand
friend class SigTrunkThread; // Needded for clearTrunk()
public:
enum Operations {
@ -207,6 +209,8 @@ public:
// Save a trunk's section to data file
bool saveTrunkData(const NamedList& list);
static const TokenDict s_operations[];
// Append an onDemand component
bool appendOnDemand(SignallingComponent* cmp, int type);
private:
// Handle command complete requests
virtual bool commandComplete(Message& msg, const String& partLine,
@ -235,6 +239,12 @@ private:
bool initTopmost(NamedList& sect, int type);
// Get the status of a topmost component
void status(SigTopmost* topmost, String& retVal);
// Initialize an on demand component
bool initOnDemand(NamedList& sect, int type);
// Get the status on an on demand component
void status(OnDemand* cmp, String& retVal);
// Destroy OnDemand object that have no reference
void checkOnDemand();
SignallingEngine* m_engine; // The signalling engine
String m_dataFile; // Trunks data file (protected by m_trunksMutex)
@ -242,6 +252,8 @@ private:
Mutex m_trunksMutex; // Lock trunk list operations
ObjList m_topmost; // Topmost non-trunk list
Mutex m_topmostMutex; // Lock topmost non-trunk list operations
ObjList m_onDemand; // List of objects created on demand
Mutex m_onDemandMutex; // Lock the list o objects created on demand
String m_statusCmd; // Prefix for status commands
};
@ -262,6 +274,20 @@ private:
String m_name; // Element name
};
class OnDemand : public TopMost
{
public:
inline OnDemand(const char* name)
: TopMost(name) { }
virtual void status(String& retVal)
{ }
virtual bool initialize(NamedList& params)
{ return true; }
virtual bool reInitialize(const NamedList& params) = 0;
virtual bool isAlive() = 0;
virtual SignallingComponent* get() = 0;
};
class SigTopmost : public TopMost
{
public:
@ -299,6 +325,32 @@ private:
SS7Layer3* m_linkset;
};
class SigSCCPUser : public SigTopmost
{
YCLASS(SigSCCPUser,SigTopmost)
public:
inline SigSCCPUser(const char* name)
: SigTopmost(name), m_user(0)
{ }
virtual ~SigSCCPUser();
virtual bool initialize(NamedList& params);
private:
SCCPUser* m_user;
};
class SigSccpGtt : public SigTopmost
{
YCLASS(SigSccpGtt,SigTopmost)
public:
inline SigSccpGtt(const char* name)
: SigTopmost(name), m_gtt(0)
{ }
virtual ~SigSccpGtt();
virtual bool initialize(NamedList& params);
private:
GTT* m_gtt;
};
// MTP Traffic Testing
class SigTesting : public SigTopmost
{
@ -315,6 +367,24 @@ private:
SS7Testing* m_testing;
};
class SigSS7Sccp : public OnDemand
{
public:
inline SigSS7Sccp(SS7SCCP* sccp)
: OnDemand(sccp? sccp->toString() : ""), m_sccp(sccp) { m_sccp->ref(); }
virtual ~SigSS7Sccp();
virtual bool initialize(NamedList& params)
{ return true; }
virtual void status(String& retVal);
virtual bool isAlive();
virtual SignallingComponent* get()
{ return m_sccp; }
virtual bool reInitialize(const NamedList& params)
{ return m_sccp ? m_sccp->initialize(&params) : false; }
private:
SS7SCCP* m_sccp;
};
// Signalling trunk (Call Controller)
class SigTrunk : public TopMost
{
@ -503,6 +573,13 @@ public:
SigSS7M2UAGateway = 0x34 | SigTopMost,
SigSS7M3UAClient = 0x35 | SigDefaults,
SigSS7M3UAGateway = 0x36 | SigTopMost,
SigSS7SCCP = 0x37 | SigOnDemand,
SigSCCP = 0x38 | SigOnDemand,
SigSCCPUserDummy = 0x39 | SigTopMost,
SigSccpGtt = 0x3a | SigTopMost,
SigSCCPManagement = 0x3b | SigDefaults,
SigSS7ItuSccpManagement = 0x3c | SigDefaults,
SigSS7AnsiSccpManagement = 0x3d | SigDefaults,
SigSS7Isup = SigTrunk::SS7Isup | SigIsTrunk | SigTopMost,
SigSS7Bicc = SigTrunk::SS7Bicc | SigIsTrunk | SigTopMost,
SigISDNPN = SigTrunk::IsdnPriNet | SigIsTrunk | SigTopMost,
@ -670,6 +747,41 @@ public:
virtual void cleanup();
};
// Implementation for a SCCP Global Title Translator
class GTTranslator : public GTT
{
YCLASS(GTTranslator,GTT)
public:
GTTranslator(const NamedList& params);
virtual ~GTTranslator();
virtual NamedList* routeGT(const NamedList& gt, const String& prefix);
virtual bool initialize(const NamedList* config);
virtual void updateTables(const NamedList& params);
};
class SCCPUserDummy : public SCCPUser
{
YCLASS(SCCPUserDummy,SCCPUser)
public:
SCCPUserDummy(const NamedList& params);
virtual ~SCCPUserDummy();
virtual HandledMSU receivedData(DataBlock& data, NamedList& params);
virtual HandledMSU notifyData(DataBlock& data, NamedList& params);
virtual bool managementNotify(SCCP::Type type, NamedList &params);
protected:
int m_ssn;
};
class SCCPHandler : public MessageHandler
{
public:
inline SCCPHandler()
: MessageHandler("sccp.generate",100) {}
virtual bool received(Message& msg);
};
static SigDriver plugin;
static SigFactory factory;
static SigNotifier s_notifier;
@ -700,6 +812,11 @@ const TokenDict SigFactory::s_compNames[] = {
{ "ss7-m3ua-gateway", SigSS7M3UAGateway },
{ "ss7-isup", SigSS7Isup },
{ "ss7-bicc", SigSS7Bicc },
{ "ss7-sccp", SigSS7SCCP },
{ "ss7-sccpu-dummy", SigSCCPUserDummy },
{ "ss7-sccp-itu-mgm", SigSS7ItuSccpManagement },
{ "ss7-sccp-ansi-mgm",SigSS7AnsiSccpManagement },
{ "ss7-gtt", SigSccpGtt },
{ "isdn-pri-net", SigISDNPN },
{ "isdn-bri-net", SigISDNBN },
{ "isdn-pri-cpe", SigISDNPC },
@ -732,6 +849,12 @@ const TokenDict SigFactory::s_compClass[] = {
MAKE_CLASS(SS7M3UAClient),
MAKE_CLASS(SS7Isup),
MAKE_CLASS(SS7Bicc),
MAKE_CLASS(SS7SCCP),
MAKE_CLASS(SCCP),
MAKE_CLASS(SCCPManagement),
MAKE_CLASS(SS7ItuSccpManagement),
MAKE_CLASS(SS7AnsiSccpManagement),
MAKE_CLASS(SCCPUserDummy),
MAKE_CLASS(ISDNPN),
MAKE_CLASS(ISDNBN),
MAKE_CLASS(ISDNPC),
@ -801,6 +924,28 @@ SignallingComponent* SigFactory::create(const String& type, const NamedList& nam
return new SS7Management(*config);
case SigSS7Testing:
return new SS7Testing(*config);
case SigSCCP:
if (ty && *ty != YSTRING("ss7-sccp"))
return 0;
case SigSS7SCCP:
{
SS7SCCP* sccp = new SS7SCCP(*config);
plugin.appendOnDemand(sccp, SigSS7SCCP);
return sccp;
}
case SigSCCPManagement:
if (!ty)
return 0;
if (*ty == "ss7-sccp-itu-mgm")
return new SS7ItuSccpManagement(*config);
else if (*ty == "ss7-sccp-ansi-mgm")
return new SS7AnsiSccpManagement(*config);
else
return 0;
case SigSS7ItuSccpManagement:
return new SS7ItuSccpManagement(*config);
case SigSS7AnsiSccpManagement:
return new SS7AnsiSccpManagement(*config);
}
return 0;
}
@ -1845,7 +1990,7 @@ SigDriver::SigDriver()
: Driver("sig","fixchans"),
m_engine(0),
m_trunksMutex(true,"SigDriver::trunks"),
m_topmostMutex(true,"SigDriver::topmost")
m_topmostMutex(true,"SigDriver::topmost"), m_onDemandMutex(true,"SigDriver::ondemand")
{
Output("Loaded module Signalling Channel");
m_statusCmd << "status " << name();
@ -1859,6 +2004,10 @@ SigDriver::~SigDriver()
m_topmostMutex.lock();
m_topmost.clear();
m_topmostMutex.unlock();
// Clear OnDemand components
m_onDemandMutex.lock();
m_onDemand.clear();
m_onDemandMutex.unlock();
if (m_engine)
delete m_engine;
}
@ -2024,6 +2173,16 @@ bool SigDriver::received(Message& msg, int id)
status(topmost,msg.retValue());
return true;
}
m_onDemandMutex.lock();
ObjList* o = m_onDemand.find(trunkName);
RefPointer<OnDemand> cmp = 0;
if (o)
cmp = static_cast<OnDemand*>(o->get());
m_onDemandMutex.unlock();
if (cmp) {
status(cmp,msg.retValue());
return true;
}
return false;
}
@ -2093,6 +2252,35 @@ void SigDriver::status(SigTopmost* topmost, String& retVal)
retVal << "\r\n";
}
void SigDriver::status(OnDemand* cmp, String& retVal)
{
retVal.clear();
retVal << "module=" << name();
retVal << ",component=" << cmp->name();
String details = "";
cmp->status(details);
if (!details.null())
retVal << "," << details;
retVal << "\r\n";
}
void SigDriver::checkOnDemand()
{
Lock lock(m_onDemandMutex);
ObjList remove;
ListIterator iter(m_onDemand);
GenObject* obj = 0;
while ((obj = iter.get())) {
OnDemand* cmp = static_cast<OnDemand*>(obj);
if (!cmp)
continue;
Lock lock1(m_engine);
if (cmp->isAlive())
continue;
m_onDemand.remove(cmp);
}
}
void SigDriver::handleEvent(SignallingEvent* event)
{
if (!event)
@ -2329,6 +2517,10 @@ bool SigDriver::commandComplete(Message& msg, const String& partLine,
for (o = m_topmost.skipNull(); o; o = o->skipNext())
itemComplete(msg.retValue(),static_cast<SigTopmost*>(o->get())->name(),partWord);
m_topmostMutex.unlock();
m_onDemandMutex.lock();
for (o = m_onDemand.skipNull(); o; o = o->skipNext())
itemComplete(msg.retValue(),static_cast<OnDemand*>(o->get())->name(),partWord);
m_onDemandMutex.unlock();
return true;
}
@ -2401,6 +2593,42 @@ bool SigDriver::commandHelp(String& retVal, const String& line)
return false;
}
bool SigDriver::appendOnDemand(SignallingComponent* cmp, int type)
{
if (!cmp)
return false;
if (type != SigFactory::SigSS7SCCP)
return false;
SS7SCCP* sccp = YOBJECT(SS7SCCP,cmp);
if (!sccp)
return false;
Lock lock(m_onDemandMutex);
if (m_onDemand.find(sccp->toString())) {
Debug(this,DebugGoOn,"Request to append duplicat of on demand component (%p): '%s'.",
cmp,cmp->toString().c_str());
return false;
}
SigSS7Sccp* dsccp = new SigSS7Sccp(sccp);
m_onDemand.append(dsccp);
DDebug(this,DebugAll,"On Demand (%p): '%s' added",cmp,cmp->toString().c_str());
return true;
}
bool SigDriver::initOnDemand(NamedList& sect, int type)
{
Lock lock(m_onDemandMutex);
ObjList* ret = m_onDemand.find(sect);
if (!ret) {
DDebug(this,DebugAll,"Can not find on demand component %s. Must not be needed.",sect.c_str());
return true;
}
OnDemand* cmp = static_cast<OnDemand*>(ret->get());
if (!cmp)
return false;
return cmp->reInitialize(sect);
}
// Append a topmost component to the list. Duplicate names are not allowed
bool SigDriver::appendTopmost(SigTopmost* topmost)
{
@ -2553,6 +2781,12 @@ bool SigDriver::initTopmost(NamedList& sect, int type)
case SigFactory::SigSS7Testing:
topmost = new SigTesting(sect);
break;
case SigFactory::SigSCCPUserDummy:
topmost = new SigSCCPUser(sect);
break;
case SigFactory::SigSccpGtt:
topmost = new SigSccpGtt(sect);
break;
default:
return false;
}
@ -2596,6 +2830,7 @@ bool SigDriver::reInitialize(NamedList& params)
SignallingComponent* router = 0;
while ((router = engine()->find("","SS7Router",router)))
YOBJECT(SS7Router,router)->printRoutes();
checkOnDemand();
return ret;
}
@ -2672,6 +2907,7 @@ void SigDriver::initialize()
installRelay(Route);
Engine::install(new IsupDecodeHandler);
Engine::install(new IsupEncodeHandler);
Engine::install(new SCCPHandler);
m_engine = SignallingEngine::self(true);
m_engine->debugChain(this);
m_engine->start();
@ -2693,6 +2929,7 @@ void SigDriver::initialize()
SignallingComponent* router = 0;
while ((router = engine()->find("","SS7Router",router)))
YOBJECT(SS7Router,router)->printRoutes();
checkOnDemand();
}
bool SigDriver::initSection(NamedList* sect)
@ -2711,6 +2948,8 @@ bool SigDriver::initSection(NamedList* sect)
ret = initTrunk(*sect,type & SigFactory::SigPrivate);
else if (type & SigFactory::SigTopMost)
ret = initTopmost(*sect,type);
else if (type & SigFactory::SigOnDemand)
ret = initOnDemand(*sect,type);
return ret;
}
@ -2828,6 +3067,86 @@ void SigLinkSet::linkStatus(String& status)
}
}
/**
* SigSS7ccp
*/
SigSS7Sccp::~SigSS7Sccp()
{
if (m_sccp) {
if (m_sccp->refcount() > 1)
Debug(&plugin,DebugWarn,"Removing alive OnDemand component '%s' [%p]",
name().c_str(),this);
TelEngine::destruct(m_sccp);
m_sccp = 0;
}
}
void SigSS7Sccp::status(String& retVal)
{
if (!m_sccp)
return;
retVal << "type=" << m_sccp->componentType();
retVal << ",sent=" << m_sccp->messagesSend();
retVal << ",received=" << m_sccp->messagesReceived();
retVal << ",translations=" << m_sccp->translations();
retVal << ",errors=" << m_sccp->errors();
}
bool SigSS7Sccp::isAlive()
{
return m_sccp && m_sccp->refcount() > 1;
}
/**
* SigSCCPUser
*/
SigSCCPUser::~SigSCCPUser()
{
if (m_user) {
plugin.engine()->remove(m_user);
TelEngine::destruct(m_user);
}
}
bool SigSCCPUser::initialize(NamedList& params)
{
#ifdef DEBUG
String tmp;
params.dump(tmp,"\r\n ",'\'',true);
Debug(DebugAll,"SigSCCPUser::initialize %s",tmp.c_str());
#endif
if (!m_user) {
m_user = new SCCPUserDummy(params);
plugin.engine()->insert(m_user);
}
return m_user && m_user->initialize(&params);
}
/**
* class SigSccpGtt
*/
SigSccpGtt::~SigSccpGtt()
{
DDebug(&plugin,DebugAll,"Destroing SigSccpGtt [%p]",this);
if (m_gtt) {
plugin.engine()->remove(m_gtt);
TelEngine::destruct(m_gtt);
}
}
bool SigSccpGtt::initialize(NamedList& params)
{
if (!m_gtt) {
m_gtt = new GTTranslator(params);
plugin.engine()->insert(m_gtt);
}
return m_gtt && m_gtt->initialize(&params);
}
/**
* SigTesting
*/
@ -4174,6 +4493,166 @@ bool IsupEncodeHandler::received(Message& msg)
return false;
}
/**
* SCCPHandler
*/
bool SCCPHandler::received(Message& msg)
{
if (!plugin.engine())
return false;
#ifdef XDEBUG
String tmp;
msg.dump(tmp,"\r\n ",'\'',true);
Debug(DebugAll,"SCCPHandler::received%s",tmp.c_str());
#endif
const char* compName = msg.getValue("component-name");
if (!compName) {
DDebug(&plugin,DebugInfo,"Received message %s widthout component name",msg.c_str());
return false;
}
SignallingComponent* cmp = plugin.engine()->find(compName);
if (!cmp) {
DDebug(&plugin,DebugInfo,"Failed to find signalling component %s",compName);
return false;
}
SCCPUserDummy* sccpUser = YOBJECT(SCCPUserDummy,cmp);
if (!sccpUser) {
DDebug(&plugin,DebugInfo,"The component %s is not an instance of SCCPUserDummy!",compName);
return false;
}
DataBlock data;
NamedString* dataNamedPointer = msg.getParam("data");
if (dataNamedPointer) {
NamedPointer* dataPointer = YOBJECT(NamedPointer,dataNamedPointer);
if (dataPointer) {
DataBlock* recvData = YOBJECT(DataBlock,dataPointer->userData());
if (recvData)
data.assign(recvData->data(),recvData->length());
} else {
String* hexData = YOBJECT(String,dataNamedPointer);
if (hexData) {
data.unHexify(hexData->c_str(),hexData->length(),' ');
}
}
}
if (data.length() == 0) {
DDebug(&plugin,DebugNote,"Received message %s with no data",msg.c_str());
return false;
}
if (msg.getParam("mgm")) {
return sccpUser->sccpNotify((SCCP::Type)msg.getIntValue("type"),msg);
}
return sccpUser->sendData(data,msg);
}
/**
* class SCCPUserDummy
*/
SCCPUserDummy::SCCPUserDummy(const NamedList& params)
:SignallingComponent(params,&params), SCCPUser(params), m_ssn(0)
{
Debug(&plugin,DebugAll,"Creating SCCPUserDummy [%p]",this);
m_ssn = params.getIntValue("ssn",0);
}
SCCPUserDummy::~SCCPUserDummy()
{
Debug(&plugin,DebugAll,"Destroing SCCPUserDummy [%p]",this);
}
HandledMSU SCCPUserDummy::receivedData(DataBlock& data, NamedList& params)
{
int ssn = params.getIntValue("ssn");
if (m_ssn && ssn != m_ssn)
return HandledMSU::Rejected;
Message* msg = new Message(params);
*msg = "sccp.message";
String hexData;
hexData.hexify(data.data(),data.length(),' ');
DataBlock* msgData = new DataBlock(data);
msg->setParam(new NamedPointer("data",msgData));
msg->setParam("hexData",hexData);
msg->setParam("msgType","indication");
Engine::enqueue(msg);
return HandledMSU::Accepted;
}
HandledMSU SCCPUserDummy::notifyData(DataBlock& data, NamedList& params)
{
Message* msg = new Message("sccp.message");
msg->copyParams(params);
String hexData;
hexData.hexify(data.data(),data.length(),' ');
DataBlock* msgData = new DataBlock(data);
msg->setParam(new NamedPointer("data",msgData));
msg->setParam("hexData",hexData);
msg->setParam("msgType","notification");
Engine::enqueue(msg);
return HandledMSU::Accepted;
}
bool SCCPUserDummy::managementNotify(SCCP::Type type, NamedList &params)
{
int ssn = params.getIntValue("ssn");
if (ssn != m_ssn)
return false;
switch (type) {
case SCCP::CoordinateConfirm:
DDebug(&plugin,DebugMild,"Subsystem %d can Go Out Of Service",m_ssn);
break;
case SCCP::CoordinateIndication:
DDebug(&plugin,DebugMild,"SSN %d received SCCP::CoordinateIndication",m_ssn);
sccpNotify(SCCP::CoordinateResponse,params);
break;
default:
return false;
}
return true;
}
/**
* class GTTranslator
*/
GTTranslator::GTTranslator(const NamedList& params)
: GTT(params)
{
DDebug(this,DebugAll,"Crated Global Title Translator [%p]",this);
}
GTTranslator::~GTTranslator()
{
DDebug(this,DebugAll,"Destroing Global Title Translator [%p]",this);
}
NamedList* GTTranslator::routeGT(const NamedList& gt, const String& prefix)
{
// TODO keep a cache!!
// Verify iff the requested gt exists in cache
// if exists return the cached translation of th GT
// if not exists send it for translation
Message* msg = new Message("sccp.route");
msg->copySubParams(gt,prefix + ".");
if (Engine::dispatch(msg)) // Append the translated GT to cache
return msg;
TelEngine::destruct(msg);
return 0;
}
void GTTranslator::updateTables(const NamedList& params)
{
Message* msg = new Message("sccp.update");
msg->copyParams(params);
Engine::enqueue(msg);
}
bool GTTranslator::initialize(const NamedList* config)
{
return GTT::initialize(config);
}
/**
* SigNotifier
*/