yate/modules/sig/camel_map.cpp

6897 lines
268 KiB
C++

/**
* camel_map.cpp
* This file is part of the YATE Project http://YATE.null.ro
*
* MAP/CAMEL TCAP <-> XML translators
*
* Yet Another Telephony Engine - a fully featured software PBX and IVR
* Copyright (C) 2004 - 2011 Null Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <yatephone.h>
#include <yatesig.h>
#include <string.h>
#include <yatexml.h>
#include <yateasn.h>
using namespace TelEngine;
namespace {
class TcapXUser;
class TcapXModule;
class XMLConnListener;
class XMLConnection;
class TcapXApplication;
class TcapToXml;
class XmlToTcap;
class TcapXNamespace;
struct MapCamelType;
struct Parameter;
struct Operation;
struct XMLMap {
Regexp name;
const char* map;
const char* tag;
int type;
};
struct TCAPMap {
const char* path;
bool isPrefix;
const String name;
};
struct AppCtxt {
const char* name;
const char* oid;
const char* ops;
};
struct Capability {
const char* name;
String ops[30];
};
class XMLConnection : public Thread
{
public:
XMLConnection(Socket* skt, TcapXApplication* app);
~XMLConnection();
// inherited from thread
void start();
void run();
void cleanup();
bool writeData(XmlFragment* frag);
private:
Socket* m_socket;
String m_address;
TcapXApplication* m_app;
XmlDomParser* m_parser;
};
class XMLConnListener : public Thread
{
public:
XMLConnListener(TcapXUser* user, const NamedList& sect);
~XMLConnListener();
virtual bool init();
virtual void run();
void cleanup();
bool createConn(Socket* skt, String& addr);
protected:
// the socket on which we accept connections
TcapXUser* m_user;
Socket m_socket;
String m_host;
int m_port;
};
class IDMap : public ObjList
{
public:
inline IDMap()
{}
inline ~IDMap()
{}
void appendID(const char* tcapID, const char* appID);
const String& findTcapID(const char* appID);
const String& findAppID(const char* tcapID);
void removeAppID(const char* appID);
};
class XmlToTcap : public GenObject, public Mutex
{
public:
enum MsgType {
Unknown,
Capability,
Tcap,
};
XmlToTcap(TcapXApplication* app);
~XmlToTcap();
inline bool hasDeclaration()
{ return m_decl; }
inline XmlElement* message()
{ return m_elem; }
inline MsgType type()
{ return m_type; }
bool validDeclaration();
bool valid();
void setXmlFragment(XmlFragment* frag);
bool checkXmlns();
bool parse(NamedList& tcapParams);
bool parse(NamedList& tcapParams, XmlElement* elem, String prefix);
bool handleComponent(NamedList& tcapParams, XmlElement* elem);
void reset();
static const TCAPMap s_tcapMap[];
const TCAPMap* findMap(String& path);
bool encodeComponent(DataBlock& payload, XmlElement* elem, bool searchArgs, int& err, Operation* op);
void encodeOperation(Operation* op, XmlElement* elem, DataBlock& payload, int& err, bool searchArgs);
private:
TcapXApplication* m_app;
XmlFragment* m_frag;
XmlDeclaration* m_decl;
XmlElement* m_elem;
MsgType m_type;
};
class TcapToXml : public GenObject, public Mutex
{
public:
enum MsgType {
Unknown,
State,
Tcap,
};
enum XmlType {
None,
Element,
Attribute,
Value,
End,
};
TcapToXml(TcapXApplication* app);
~TcapToXml();
inline MsgType type()
{ return m_type; }
bool buildXMLMessage(NamedList& msg, XmlFragment* frag, MsgType type);
static const XMLMap s_xmlMap[];
void reset();
void addToXml(XmlElement* root, const XMLMap* map, NamedString* val);
void addComponentsToXml(XmlElement* root, NamedList& params, AppCtxt* ctxt);
const XMLMap* findMap(String& elem);
void addParametersToXml(XmlElement* elem, String& payloadHex, Operation* op, bool searchArgs = true);
void decodeTcapToXml(TelEngine::XmlElement*, TelEngine::DataBlock&, Operation* op, unsigned int index = 0, bool seachArgs = true);
bool decodeOperation(Operation* op, XmlElement* elem, DataBlock& data, bool searchArgs = true);
private:
TcapXApplication* m_app;
MsgType m_type;
};
class TcapXUser : public TCAPUser, public Mutex
{
public:
enum UserType {
MAP,
CAMEL,
};
TcapXUser(const char* name);
~TcapXUser();
virtual bool tcapIndication(NamedList& params);
virtual bool managementNotify(SCCP::Type type, NamedList& params);
bool findTCAP(const char* name);
int managementState();
bool initialize(NamedList& sect);
bool createApplication(Socket* skt, String& addr);
void setListener(XMLConnListener* list);
void removeApp(TcapXApplication* app);
SS7TCAPError applicationRequest(TcapXApplication* app, NamedList& params, int reqType);
bool sendToApp(NamedList& params, TcapXApplication* app = 0);
TcapXApplication* findApplication(NamedList& params);
void reorderApps(TcapXApplication* app);
inline UserType type()
{ return m_type; }
inline bool printMessages()
{ return m_printMsg; }
inline bool addEncoding()
{ return m_addEnc; }
inline unsigned int applicationCount()
{
Lock l(m_appsMtx);
return m_apps.count();
}
void statusString(String& str);
protected:
ObjList m_apps;
Mutex m_appsMtx;
XMLConnListener* m_listener;
ObjList m_trIDs;
UserType m_type;
bool m_printMsg;
bool m_addEnc;
};
class TcapXApplication : public RefObject, public Mutex
{
public:
enum State {
Waiting,
Active,
ShutDown,
Inactive,
};
enum ParamType {
Unknown,
Null,
Bool,
Integer,
OID,
HexString,
BitString,
TBCD,
AddressString,
AppString,
Enumerated,
Choice,
Sequence,
SequenceOf,
SetOf,
GSMString,
Flags,
CellIdFixedLength,
LAIFixedLength,
CalledPartyNumber,
CallingPartyNumber,
LocationNumber,
OriginalCalledNumber,
RedirectingNumber,
GenericNumber,
ChargeNumber,
HiLayerCompat,
UserServiceInfo,
RedirectionInformation,
None,
};
enum EncType {
BoolEnc,
IntEnc,
OIDEnc,
StringEnc,
NullEnc,
HexEnc,
TelephonyEnc,
NoEnc,
};
enum Error {
NoError,
DataMissing,
UnexpectedDataValue,
};
TcapXApplication(const char* name, Socket* skt, TcapXUser* user);
~TcapXApplication();
bool hasCapability(const char* oper);
bool handleXML();
void receivedXML(XmlFragment* frag);
const String& toString() const
{ return m_name; }
void setIO(XMLConnection* io);
void reportState(State state, const char* error = 0);
void closeConnection();
bool supportCapability(const String& capab);
void sendStateResponse(const char* error = 0);
bool handleCapability(NamedList& params);
bool handleTcap(NamedList& params);
bool handleIndication(NamedList& params);
void reportError(const char* err);
bool sendTcapMsg(NamedList& params);
bool canHandle(NamedList& params);
void status(NamedList& status);
inline State state()
{ return m_state; }
inline unsigned int trCount()
{ return m_ids.count() + m_pending.count(); }
inline TcapXUser::UserType type()
{ return m_type; }
inline bool addEncoding()
{ return (m_user ? m_user->addEncoding() : false); }
private:
IDMap m_ids;
IDMap m_pending;
ObjList m_capab;
XMLConnection* m_io;
String m_name;
TcapXUser* m_user;
unsigned int m_sentXml;
unsigned int m_receivedXml;
unsigned int m_sentTcap;
unsigned int m_receivedTcap;
State m_state;
TcapToXml m_tcap2Xml;
XmlToTcap m_xml2Tcap;
TcapXUser::UserType m_type;
};
class TcapXModule : public Module
{
public:
TcapXModule();
virtual ~TcapXModule();
//inherited methods
virtual void initialize();
// uninstall relays and message handlers
bool unload();
protected:
// inherited methods
virtual bool received(Message& msg, int id);
virtual void statusModule(String& str);
void initUsers(Configuration& cfg);
virtual void statusParams(String& str);
virtual void statusDetail(String& str);
unsigned int applicationCount();
private:
bool m_init;
Mutex m_usersMtx;
ObjList m_users;
};
INIT_PLUGIN(TcapXModule);
UNLOAD_PLUGIN(unloadNow)
{
if (unloadNow && !__plugin.unload())
return false;
return true;
}
const String s_namespace = "http://yate.null.ro/xml/tcap/v1";
static const String s_msgTag = "m";
static const String s_capabTag = "c";
static const String s_component = "component";
static const String s_typeStr = "type";
static const String s_tagAttr = "tag";
static const String s_encAttr = "enc";
static const String s_qualifierAttr = "qualifier";
static const String s_planAttr = "plan";
static const String s_natureAttr = "nature";
static const String s_innAttr = "inn";
static const String s_completeAttr = "complete";
static const String s_restrictAttr = "restrict";
static const String s_screenedtAttr = "screened";
static const String s_tcapUser = "tcap.user";
static const String s_tcapRequestError = "tcap.request.error";
static const String s_tcapLocalTID = "tcap.transaction.localTID";
static const String s_tcapRemoteTID = "tcap.transaction.remoteTID";
static const String s_tcapAppCtxt = "tcap.dialogPDU.application-context-name";
static const String s_tcapReqType = "tcap.request.type";
static const String s_tcapCompCount = "tcap.component.count";
static const String s_tcapCompPrefix = "tcap.component";
static const String s_tcapCompPrefixSep = "tcap.component.";
static const String s_tcapAbortCause = "tcap.transaction.abort.cause";
static const String s_tcapAbortInfo = "tcap.transaction.abort.information";
static const String s_tcapCompType = "componentType";
static const String s_tcapOpCodeType = "operationCodeType";
static const String s_tcapOpCode = "operationCode";
static const String s_tcapErrCodeType = "errorCodeType";
static const String s_tcapErrCode = "errorCode";
static const String s_tcapProblemCode = "problemCode";
static const TokenDict s_tagTypes[] = {
{"universal", AsnTag::Universal},
{"application", AsnTag::Application},
{"context", AsnTag::Context},
{"private", AsnTag::Private},
{"", -1},
};
struct Parameter {
const String name;
const AsnTag& tag;
bool isOptional;
TcapXApplication::ParamType type;
const void* content;
};
struct Operation {
const String name;
bool local;
int code;
const AsnTag& argTag;
const Parameter* args;
const AsnTag& retTag;
const Parameter* res;
};
static const TokenDict s_dict_numNature[] = {
{ "unknown", 0x00 },
{ "international", 0x10 },
{ "national", 0x20 },
{ "network-specific", 0x30 },
{ "subscriber", 0x40 },
{ "reserved", 0x50 },
{ "abbreviated", 0x60 },
{ "extension-reserved", 0x70 },
{ 0, 0 },
};
// Numbering Plan Indicator
static const TokenDict s_dict_numPlan[] = {
{ "unknown", 0 },
{ "isdn", 1 },
{ "data", 3 },
{ "telex", 4 },
{ "land-mobile", 6 },
{ "national", 8 },
{ "private", 9 },
{ "extension-reserved", 15 },
{ 0, 0 },
};
struct MapCamelType {
TcapXApplication::ParamType type;
TcapXApplication::EncType encoding;
bool (*decode)(const Parameter*, MapCamelType*, AsnTag& tag, DataBlock&, XmlElement*, bool, int& err);
bool (*encode)(const Parameter*, MapCamelType*, DataBlock&, XmlElement*, int& err);
};
static const MapCamelType* findType(TcapXApplication::ParamType type);
static AsnTag s_sequenceTag(AsnTag::Universal,AsnTag::Constructor,16);
static AsnTag s_intTag(AsnTag::Universal, AsnTag::Primitive, 2);
static AsnTag s_bitsTag(AsnTag::Universal, AsnTag::Primitive, 3);
static AsnTag s_nullTag(AsnTag::Universal, AsnTag::Primitive, 5);
static AsnTag s_oidTag(AsnTag::Universal, AsnTag::Primitive, 6);
static AsnTag s_hexTag(AsnTag::Universal, AsnTag::Primitive, 4);
static AsnTag s_numStrTag(AsnTag::Universal, AsnTag::Primitive, 18);
static AsnTag s_noTag(AsnTag::Universal, AsnTag::Primitive, 0);
static AsnTag s_enumTag(AsnTag::Universal, AsnTag::Primitive, 10);
static const Parameter* findParam(const Parameter* param, const String& tag)
{
if (!param)
return 0;
XDebug(DebugAll,"findParam(param=%s,tag=%s)",param->name.c_str(),tag.c_str());
if (param->type == TcapXApplication::Choice && param->content) {
const Parameter* p = static_cast<const Parameter*>(param->content);
if (p)
return findParam(p,tag);
}
while (param && !TelEngine::null(param->name)) {
if (tag == param->name)
return param;
param++;
}
return 0;
}
static bool encodeParam(const Parameter* param, DataBlock& data, XmlElement* elem, int& err);
static bool encodeRaw(const Parameter* param, DataBlock& payload, XmlElement* elem, int& err)
{
if (!elem)
return true;
XDebug(&__plugin,DebugAll,"encodeRaw(param=[%p],elem=%s[%p])",param,elem->getTag().c_str(),elem);
bool hasChildren = false;
bool status = true;
while (XmlElement* child = elem->pop()) {
hasChildren = true;
DataBlock db;
Parameter* p = (Parameter*)findParam(param,elem->getTag());
if (p)
status = encodeParam(p,db,child,err);
else
status = encodeRaw(p,db,child,err);
payload.append(db);
TelEngine::destruct(child);
if (!status)
break;
}
AsnTag tag;
String* clas = elem->getAttribute(s_typeStr);
if (TelEngine::null(clas))
return false;
tag.classType((AsnTag::Class)lookup(*clas,s_tagTypes,AsnTag::Universal));
clas = elem->getAttribute(s_tagAttr);
if (TelEngine::null(clas))
return false;
tag.code(clas->toInteger());
String text = elem->getText();
if (!hasChildren) {
clas = elem->getAttribute(s_encAttr);
if (TelEngine::null(clas))
return false;
tag.type(AsnTag::Primitive);
if (*clas == "hex")
payload.unHexify(text.c_str(),text.length(),' ');
else if (*clas == "int")
payload.insert(ASNLib::encodeInteger(text.toInteger(),false));
else if (*clas == "str")
payload.insert(ASNLib::encodeUtf8(text,false));
else if (*clas == "null")
payload.clear();
else if (*clas == "oid") {
ASNObjId obj = text;
payload.insert(ASNLib::encodeOID(obj,false));
}
else if (*clas == "bool")
payload.insert(ASNLib::encodeBoolean(text.toBoolean(),false));
payload.insert(ASNLib::buildLength(payload));
AsnTag::encode(tag.classType(),tag.type(),tag.code(),payload);
}
else {
tag.type(AsnTag::Constructor);
payload.insert(ASNLib::buildLength(payload));
AsnTag::encode(tag.classType(),tag.type(),tag.code(),payload);
}
return true;
}
static bool encodeParam(const Parameter* param, DataBlock& data, XmlElement* elem, int& err)
{
if (!(param && elem))
return false;
XDebug(&__plugin,DebugAll,"encodeParam(param=%s[%p],elem=%s[%p])",param->name.c_str(),param,elem->getTag().c_str(),elem);
MapCamelType* type = (MapCamelType*)findType(param->type);
bool ok = true;
if (!type)
ok = encodeRaw(param,data,elem,err);
else {
XmlElement* child = (elem->getTag() == s_component ? elem->findFirstChild(&param->name) : elem);
if (!child) {
if (!param->isOptional) {
err = TcapXApplication::DataMissing;
return false;
}
return true;
}
ok = type->encode(param,type,data,child,err);
elem->removeChild(child);
}
String str;
str.hexify(data.data(),data.length(),' ');
XDebug(&__plugin,DebugAll,"encodeParam(param=%s[%p],elem=%s[%p] has %ssucceeded, encodedData=%s)",param->name.c_str(),param,
elem->getTag().c_str(),elem,(ok ? "" : "not "),str.c_str());
return ok;
}
static bool decodeRaw(XmlElement* elem, DataBlock& data, bool singleParam = false)
{
if (!(elem && data.length()))
return false;
DDebug(&__plugin,DebugAll,"decodeRaw(elem=%s[%p])",elem->getTag().c_str(),elem);
while (data.length()) {
AsnTag tag;
AsnTag::decode(tag,data);
data.cut(-tag.coding().length());
XmlElement* child = new XmlElement("u");
elem->addChild(child);
child->setAttributeValid(s_typeStr,lookup(tag.classType(),s_tagTypes,""));
child->setAttributeValid(s_tagAttr,String((unsigned int)tag.code()));
if (tag.type() == AsnTag::Primitive) {
String enc;
String value;
int len = 0;
u_int8_t fullTag = tag.classType() | tag.type() | tag.code();
switch (fullTag) {
case ASNLib::BOOLEAN: {
bool val;
if (ASNLib::decodeBoolean(data,&val,true) < 0)
return false;
value = String::boolText(val);
enc = "bool";
}
break;
case ASNLib::INTEGER: {
u_int64_t val;
if (ASNLib::decodeInteger(data,val,sizeof(val),true) < 0)
return false;
// to do fix conversion from u_int64_t
value = String((int)val);
enc = "int";
}
break;
case ASNLib::OBJECT_ID: {
ASNObjId val;
if (ASNLib::decodeOID(data,&val,true) < 0)
return false;
value = val.toString();
enc = "oid";
}
break;
case ASNLib::UTF8_STR: {
if (ASNLib::decodeUtf8(data,&enc,true) < 0)
return false;
value = enc;
enc = "str";
}
break;
case ASNLib::NULL_ID:
if (ASNLib::decodeNull(data,true) < 0)
return false;
enc = "null";
break;
case ASNLib::NUMERIC_STR:
case ASNLib::PRINTABLE_STR:
case ASNLib::IA5_STR:
case ASNLib::VISIBLE_STR: {
int type;
if (ASNLib::decodeString(data,&enc,&type,true) < 0)
return false;
value = enc;
enc = "str";
}
break;
default:
len = ASNLib::decodeLength(data);
value.hexify(data.data(),len,' ');
data.cut(-len);
enc = "hex";
break;
}
child->setAttributeValid(s_encAttr,enc);
child->addText(value);
}
else {
int len = ASNLib::decodeLength(data);
DataBlock payload(data.data(),len);
data.cut(-len);
decodeRaw(child,payload);
}
if (singleParam)
break;
}
return true;
}
static bool decodeParam(const Parameter* param, AsnTag& tag, DataBlock& data, XmlElement* elem, bool addEnc, int& err)
{
if (!(param && elem && data.length()))
return false;
String str;
str.hexify(data.data(),data.length(),' ');
XDebug(&__plugin,DebugAll,"decodeParam(param=%s[%p],elem=%s[%p]) - data = %s",param->name.c_str(),param,elem->getTag().c_str(),
elem,str.c_str());
MapCamelType* type = (MapCamelType*)findType(param->type);
bool ok = true;
if (!type)
ok = decodeRaw(elem,data,true);
else
ok = type->decode(param,type,tag,data,elem,addEnc,err);
XDebug(&__plugin,DebugAll,"decodeParam(param=%s[%p],elem=%s[%p]) %s",param->name.c_str(),param,elem->getTag().c_str(),
elem, (ok ? "OK" : "FAILED"));
return ok;
}
static unsigned int decodeBCD(unsigned int length, String& digits, unsigned char* buff)
{
if (!(buff && length))
return 0;
static const char s_digits[] = "0123456789*#ABC";
unsigned int index = 0;
while (index < length) {
digits += s_digits[(buff[index] & 0x0f)];
u_int8_t odd = (buff[index] >> 4);
if ((odd & 0x0f) != 0x0f)
digits += s_digits[(buff[index] >> 4)];
index++;
}
XDebug(&__plugin,DebugAll,"Decoded BCD digits=%s",digits.c_str());
return index;
}
void encodeBCD(const String& digits, DataBlock& data)
{
XDebug(&__plugin,DebugAll,"encodeBCD(digit=%s)",digits.c_str());
unsigned int len = digits.length() / 2 + (digits.length() % 2 ? 1 : 0);
unsigned char buf[32];
unsigned int i = 0;
unsigned int j = 0;
bool odd = false;
while((i < digits.length()) && (j < len)) {
char c = digits[i++];
unsigned char d = 0;
if (('0' <= c) && (c <= '9'))
d = c - '0';
else if ('*' == c)
d = 10;
else if ('#' == c)
d = 11;
else if ('a' == c || 'A' == c)
d = 12;
else if ('b' == c || 'B' == c)
d = 13;
else if ('c' == c || 'C' == c)
d = 14;
// else if ('.' == c)
// d = 15;
else
continue;
odd = !odd;
if (odd)
buf[j] = d;
else
buf[j++] |= (d << 4);
}
if (odd)
buf[j++] |= 0xf0;
data.append(&buf,j);
}
static bool decodeTBCD(const Parameter* param, MapCamelType* type, AsnTag& tag, DataBlock& data, XmlElement* parent, bool addEnc, int& err)
{
if (!(param && type && data.length() && parent))
return false;
XDebug(&__plugin,DebugAll,"decodeTBCD(param=%s[%p],elem=%s[%p])",param->name.c_str(),param,parent->getTag().c_str(),parent);
if (param->tag != tag)
return false;
data.cut(-tag.coding().length());
XmlElement* child = new XmlElement(param->name);
parent->addChild(child);
if (addEnc)
child->setAttribute(s_encAttr,"str");
int len = ASNLib::decodeLength(data);
String digits;
len = decodeBCD(len,digits,data.data(0,len));
data.cut(-len);
child->addText(digits);
return true;
}
static bool encodeTBCD(const Parameter* param, MapCamelType* type, DataBlock& data, XmlElement* elem, int& err)
{
if (!(param && elem))
return false;
XDebug(&__plugin,DebugAll,"encodeTBCD(param=%s[%p],elem=%s[%p])",param->name.c_str(),param,elem->getTag().c_str(),elem);
const String& text = elem->getText();
encodeBCD(text,data);
data.insert(ASNLib::buildLength(data));
data.insert(param->tag.coding());
return true;
}
static bool decodeTel(const Parameter* param, MapCamelType* type, AsnTag& tag, DataBlock& data, XmlElement* parent, bool addEnc, int& err)
{
if (!(param && type && data.length() && parent))
return false;
XDebug(&__plugin,DebugAll,"decodeTel(param=%s[%p],elem=%s[%p],datalen=%d)",param->name.c_str(),param,parent->getTag().c_str(),
parent,data.length());
if (param->tag != tag)
return false;
data.cut(-tag.coding().length());
XmlElement* child = new XmlElement(param->name);
parent->addChild(child);
int len = ASNLib::decodeLength(data);
if (len < 1)
return false;
u_int8_t attr = data[0];
child->setAttribute(s_natureAttr,lookup((attr & 0x70),s_dict_numNature,"unknown"));
child->setAttribute(s_planAttr,lookup((attr & 0x0f),s_dict_numPlan,"unknown"));
if ((attr & 0x0f) == 1)
child->setAttribute(s_encAttr,"e164");
else if ((attr & 0x0f) == 6)
child->setAttribute(s_encAttr,"e212");
String digits;
decodeBCD(len - 1,digits,data.data(1,len - 1 ));
data.cut(-len);
child->addText(digits);
return true;
}
static bool encodeTel(const Parameter* param, MapCamelType* type, DataBlock& data, XmlElement* elem, int& err)
{
if (!(param && elem))
return false;
XDebug(&__plugin,DebugAll,"encodeTel(param=%s[%p],elem=%s[%p],datalen=%d)",param->name.c_str(),param,elem->getTag().c_str(),
elem,data.length());
u_int8_t first = 0x80; // noExtension bit set
first |= lookup(elem->attribute(s_natureAttr),s_dict_numNature,0);
first |= lookup(elem->attribute(s_planAttr),s_dict_numPlan,0);
data.append(&first,sizeof(first));
const String& digits = elem->getText();
encodeBCD(digits,data);
data.insert(ASNLib::buildLength(data));
data.insert(param->tag.coding());
return true;
}
static bool decodeHex(const Parameter* param, MapCamelType* type, AsnTag& tag, DataBlock& data, XmlElement* parent, bool addEnc, int& err)
{
if (!(param && type && data.length() && parent))
return false;
XDebug(&__plugin,DebugAll,"decodeHex(param=%s[%p],elem=%s[%p],datalen=%d)",param->name.c_str(),param,parent->getTag().c_str(),
parent,data.length());
if (param->tag != tag)
return false;
data.cut(-tag.coding().length());
XmlElement* child = new XmlElement(param->name);
parent->addChild(child);
if (addEnc)
child->setAttribute(s_encAttr,"oid");
int len = ASNLib::decodeLength(data);
String octets;
octets.hexify(data.data(),len,' ');
data.cut(-len);
child->addText(octets);
return true;
}
static bool encodeHex(const Parameter* param, MapCamelType* type, DataBlock& data, XmlElement* elem, int& err)
{
if (!(param && elem))
return false;
XDebug(&__plugin,DebugAll,"encodeHexparam=%s[%p],elem=%s[%p])",param->name.c_str(),param,elem->getTag().c_str(),elem);
const String& text = elem->getText();
data.unHexify(text.c_str(),text.length(),' ');
data.insert(ASNLib::buildLength(data));
data.insert(param->tag.coding());;
return true;
}
static bool decodeOID(const Parameter* param, MapCamelType* type, AsnTag& tag, DataBlock& data, XmlElement* parent, bool addEnc, int& err)
{
if (!(param && type && data.length() && parent))
return false;
XDebug(&__plugin,DebugAll,"decodeOID(param=%s[%p],elem=%s[%p],datalen=%d)",param->name.c_str(),param,parent->getTag().c_str(),
parent,data.length());
if (param->tag != tag)
return false;
data.cut(-tag.coding().length());
XmlElement* child = new XmlElement(param->name);
parent->addChild(child);
if (addEnc)
child->setAttribute(s_encAttr,"oid");
ASNObjId obj;
ASNLib::decodeOID(data,&obj,false);
child->addText(obj.toString());
return true;
}
static bool encodeOID(const Parameter* param, MapCamelType* type, DataBlock& data, XmlElement* elem, int& err)
{
if (!(param && elem))
return false;
XDebug(&__plugin,DebugAll,"encodeOID(param=%s[%p],elem=%s[%p])",param->name.c_str(),param,elem->getTag().c_str(),elem);
ASNObjId oid = elem->getText();
data.append(ASNLib::encodeOID(oid,false));
data.insert(ASNLib::buildLength(data));
data.insert(param->tag.coding());
return true;
}
static bool decodeNull(const Parameter* param, MapCamelType* type, AsnTag& tag, DataBlock& data, XmlElement* parent, bool addEnc, int& err)
{
if (!(param && type && data.length() && parent))
return false;
XDebug(&__plugin,DebugAll,"decodeNull(param=%s[%p],elem=%s[%p],datalen=%d)",param->name.c_str(),param,parent->getTag().c_str(),
parent,data.length());
if (param->tag != tag)
return false;
data.cut(-tag.coding().length());
XmlElement* child = new XmlElement(param->name);
parent->addChild(child);
if (addEnc)
child->setAttribute(s_encAttr,"null");
int len = ASNLib::decodeNull(data,false);
data.cut(-len);
return true;
}
static bool encodeNull(const Parameter* param, MapCamelType* type, DataBlock& data, XmlElement* elem, int& err)
{
if (!(param && elem))
return false;
XDebug(&__plugin,DebugAll,"encodeNull(param=%s[%p],elem=%s[%p])",param->name.c_str(),param,elem->getTag().c_str(),elem);
ASNObjId oid = elem->getText();
data.append(ASNLib::encodeNull(false));
data.insert(ASNLib::buildLength(data));
data.insert(param->tag.coding());
return true;
}
static bool decodeInt(const Parameter* param, MapCamelType* type, AsnTag& tag, DataBlock& data, XmlElement* parent, bool addEnc, int& err)
{
if (!(param && type && data.length() && parent))
return false;
XDebug(&__plugin,DebugAll,"decodeInt(param=%s[%p],elem=%s[%p],datalen=%d)",param->name.c_str(),param,parent->getTag().c_str(),
parent,data.length());
if (param->tag != tag)
return false;
data.cut(-tag.coding().length());
XmlElement* child = new XmlElement(param->name);
parent->addChild(child);
if (addEnc)
child->setAttribute(s_encAttr,"int");
u_int64_t val;
ASNLib::decodeInteger(data,val,sizeof(val),false);
child->addText(String((int)val));
return true;
}
static bool encodeInt(const Parameter* param, MapCamelType* type, DataBlock& data, XmlElement* elem, int& err)
{
if (!(param && elem))
return false;
XDebug(&__plugin,DebugAll,"encodeInt(param=%s[%p],elem=%s[%p])",param->name.c_str(),param,elem->getTag().c_str(),elem);
u_int64_t val = elem->getText().toInteger();
data.append(ASNLib::encodeInteger(val,false));
data.insert(ASNLib::buildLength(data));
data.insert(param->tag.coding());
return true;
}
static bool decodeSeq(const Parameter* param, MapCamelType* type, AsnTag& tag, DataBlock& data, XmlElement* parent, bool addEnc, int& err)
{
if (!(param && type && data.length() && parent))
return false;
XDebug(&__plugin,DebugAll,"decodeSeq(param=%s[%p],elem=%s[%p],datalen=%d,first=0x%x)",param->name.c_str(),param,
parent->getTag().c_str(),parent,data.length(),data[0]);
if (param->tag != tag)
return false;
data.cut(-tag.coding().length());
int len = ASNLib::decodeLength(data);
if (len < 0)
return false;
XmlElement* child = new XmlElement(param->name);
parent->addChild(child);
if (param->content) {
const Parameter* params= static_cast<const Parameter*>(param->content);
while (params && !TelEngine::null(params->name)) {
AsnTag childTag;
AsnTag::decode(childTag,data);
if (!decodeParam(params,childTag,data,child,addEnc,err)) {
if (!params->isOptional) {
err = TcapXApplication::DataMissing;
return false;
}
else {
params++;
continue;
}
}
params++;
}
}
return true;
}
static bool encodeSeq(const Parameter* param, MapCamelType* type, DataBlock& data, XmlElement* elem, int& err)
{
if (!(param && elem))
return false;
XDebug(&__plugin,DebugAll,"encodeSeq(param=%s[%p],elem=%s[%p])",param->name.c_str(),param,elem->getTag().c_str(),elem);
if (param->content) {
const Parameter* params= static_cast<const Parameter*>(param->content);
while (params && !TelEngine::null(params->name)) {
const String name = params->name;
XmlElement* child = elem->findFirstChild(&name);
if (!child) {
if (!params->isOptional) {
err = TcapXApplication::DataMissing;
return false;
}
else {
params++;
continue;
}
}
DataBlock db;
if (!encodeParam(params,db,child,err))
return false;
data.append(db);
elem->removeChild(child);
params++;
}
}
if (param->tag != s_noTag) {
data.insert(ASNLib::buildLength(data));
data.insert(param->tag.coding());
}
return true;
}
static bool decodeSeqOf(const Parameter* param, MapCamelType* type, AsnTag& tag, DataBlock& data, XmlElement* parent, bool addEnc,
int& err)
{
if (!(param && type && data.length() && parent))
return false;
XDebug(&__plugin,DebugAll,"decodeSeqOf(param=%s[%p],elem=%s[%p],datalen=%d)",param->name.c_str(),param,parent->getTag().c_str(),
parent,data.length());
if (param->tag != tag)
return false;
data.cut(-tag.coding().length());
int len = ASNLib::decodeLength(data);
if (len < 0)
return false;
XmlElement* child = new XmlElement(param->name);
parent->addChild(child);
int initLength = data.length();
int payloadLen = len;
if (param->content) {
const Parameter* params= static_cast<const Parameter*>(param->content);
while (params && !TelEngine::null(params->name) && payloadLen) {
AsnTag childTag;
AsnTag::decode(childTag,data);
if (!decodeParam(params,childTag,data,child,addEnc,err)) {
if (!param->isOptional) {
err = TcapXApplication::DataMissing;
return false;
}
else
break;
}
payloadLen = data.length() - (initLength - len);
}
}
return true;
}
static bool encodeSeqOf(const Parameter* param, MapCamelType* type, DataBlock& data, XmlElement* elem, int& err)
{
if (!(param && elem))
return false;
XDebug(&__plugin,DebugAll,"encodeSeqOf(param=%s[%p],elem=%s[%p])",param->name.c_str(),param,elem->getTag().c_str(),elem);
if (param->content) {
const Parameter* params = static_cast<const Parameter*>(param->content);
XmlElement* child = elem->pop();
while (params && !TelEngine::null(params->name) && child) {
if (!(child->getTag() == params->name)) {
if (!param->isOptional) {
TelEngine::destruct(child);
err = TcapXApplication::DataMissing;
return false;
}
else
continue;
}
DataBlock db;
if (!encodeParam(params,db,child,err)) {
TelEngine::destruct(child);
return false;
}
data.append(db);
TelEngine::destruct(child);
child = elem->pop();
}
}
if (param->tag != s_noTag) {
data.insert(ASNLib::buildLength(data));
data.insert(param->tag.coding());
}
return true;
}
static bool decodeChoice(const Parameter* param, MapCamelType* type, AsnTag& tag, DataBlock& data, XmlElement* parent, bool addEnc, int& err)
{
if (!(param && type && data.length() && parent))
return false;
XDebug(&__plugin,DebugAll,"decodeChoice(param=%s[%p],elem=%s[%p],datalen=%d)",param->name.c_str(),param,parent->getTag().c_str(),
parent,data.length());
if (param->tag != s_noTag) {
if (param->tag != tag)
return false;
data.cut(-tag.coding().length());
int len = ASNLib::decodeLength(data);
if (len < 0)
return false;
}
XmlElement* child = new XmlElement(param->name);
parent->addChild(child);
if (param->content) {
const Parameter* params= static_cast<const Parameter*>(param->content);
while (params && !TelEngine::null(params->name)) {
AsnTag childTag;
AsnTag::decode(childTag,data);
if (!decodeParam(params,childTag,data,child,addEnc,err)) {
params++;
continue;
}
break;
}
}
return true;
}
static bool encodeChoice(const Parameter* param, MapCamelType* type, DataBlock& data, XmlElement* elem, int& err)
{
if (!(param && elem))
return false;
XDebug(&__plugin,DebugAll,"encodeChoice(param=%s[%p],elem=%s[%p])",param->name.c_str(),param,elem->getTag().c_str(),elem);
if (param->content) {
const Parameter* params = static_cast<const Parameter*>(param->content);
XmlElement* child = elem->pop();
while (child && params && !TelEngine::null(params->name)) {
if (child->getTag() == params->name) {
DataBlock db;
if (!encodeParam(params,db,child,err)) {
TelEngine::destruct(child);
return false;
}
data.append(db);
if (param->tag != s_noTag) {
data.insert(ASNLib::buildLength(data));
data.insert(param->tag.coding());
}
TelEngine::destruct(child);
return true;
}
params++;
}
TelEngine::destruct(child);
}
return false;
}
static bool decodeEnumerated(const Parameter* param, MapCamelType* type, AsnTag& tag, DataBlock& data, XmlElement* parent, bool addEnc, int& err)
{
if (!(param && type && data.length() && parent))
return false;
XDebug(&__plugin,DebugAll,"decodeEnumerated(param=%s[%p],elem=%s[%p],datalen=%d)",param->name.c_str(),param,parent->getTag().c_str(),
parent,data.length());
if (param->tag != tag)
return false;
data.cut(-tag.coding().length());
int len = ASNLib::decodeLength(data);
if (len < 0)
return false;
XmlElement* child = new XmlElement(param->name);
parent->addChild(child);
u_int8_t val = data[0];
data.cut(-1);
if (param->content) {
const TokenDict* dict = static_cast<const TokenDict*>(param->content);
if (!dict)
return false;
child->addText(lookup(val,dict,""));
if (addEnc)
child->setAttribute(s_encAttr,"str");
}
else {
child->addText(String(val));
if (addEnc)
child->setAttribute(s_encAttr,"int");
}
return true;
}
static bool encodeEnumerated(const Parameter* param, MapCamelType* type, DataBlock& data, XmlElement* elem, int& err)
{
if (!(param && elem))
return false;
XDebug(&__plugin,DebugAll,"encodeEnumerated(param=%s[%p],elem=%s[%p])",param->name.c_str(),param,elem->getTag().c_str(),elem);
if (param->content) {
const TokenDict* dict = static_cast<const TokenDict*>(param->content);
if (!dict)
return false;
const String& text = elem->getText();
u_int8_t val = lookup(text,dict,0);
if (val < 0) {
err = TcapXApplication::UnexpectedDataValue;
return false;
}
data.append(&val,sizeof(val));
}
if (param->tag != s_noTag) {
data.insert(ASNLib::buildLength(data));
data.insert(param->tag.coding());
}
return true;
}
static bool decodeBitString(const Parameter* param, MapCamelType* type, AsnTag& tag, DataBlock& data, XmlElement* parent, bool addEnc, int& err)
{
if (!(param && type && data.length() && parent))
return false;
XDebug(&__plugin,DebugAll,"decodeBitString(param=%s[%p],elem=%s[%p],datalen=%d)",param->name.c_str(),param,parent->getTag().c_str(),
parent,data.length());
if (param->tag != tag)
return false;
data.cut(-tag.coding().length());
XmlElement* child = new XmlElement(param->name);
parent->addChild(child);
if (addEnc)
child->setAttribute(s_encAttr,"str");
String val, str;
int value = 0;
ASNLib::decodeBitString(data,&val,false);
for (unsigned int i = 0; i < val.length(); i++) {
char c = val[1];
if (c == '1') {
int mask = 1 << i;
value |= mask;
}
}
if (param->content) {
const TokenDict* dict = static_cast<const TokenDict*>(param->content);
if (!dict)
return true;
while (dict->token){
if ((dict->value & value) == dict->value)
str.append(dict->token,",");
dict++;
}
}
child->addText(str);
return true;
}
static bool encodeBitString(const Parameter* param, MapCamelType* type, DataBlock& data, XmlElement* elem, int& err)
{
if (!(param && elem))
return false;
XDebug(&__plugin,DebugAll,"encodeBitString(param=%s[%p],elem=%s[%p])",param->name.c_str(),param,elem->getTag().c_str(),elem);
if (param->content) {
const TokenDict* dict = static_cast<const TokenDict*>(param->content);
String val;
int value = 0;
if (dict) {
const String& text = elem->getText();
ObjList* list = text.split(',',false);
while(dict->token){
if (list->find(dict->token))
value |= dict->value;
dict++;
}
TelEngine::destruct(list);
}
int size = sizeof(value) * 8;
bool start = false;
while (size > 0) {
size--;
u_int8_t b = (value >> size) & 0x01;
if (b == 1 && !start)
start = true;
if (start)
val = (b == 1? "1" : "0") + val;
}
data.append(ASNLib::encodeBitString(val,false));
}
if (param->tag != s_noTag) {
data.insert(ASNLib::buildLength(data));
data.insert(param->tag.coding());
}
return true;
}
static void decodeGSM7Bit(DataBlock& data, int& len, String& decoded)
{
u_int8_t bits = 0;
for (int i = 0; i < len; i++) {
if (bits == 8)
bits = 1;
char c = (data[i] << bits) & 0x7f;
if (i > 0)
c |= data[i - 1] >> (8 - bits);
decoded << c;
bits++;
}
data.cut(-len);
}
static bool decodeGSMString(const Parameter* param, MapCamelType* type, AsnTag& tag, DataBlock& data, XmlElement* parent, bool addEnc, int& err)
{
if (!(param && type && data.length() && parent))
return false;
XDebug(&__plugin,DebugAll,"decodeGSMString(param=%s[%p],elem=%s[%p],datalen=%d)",param->name.c_str(),param,parent->getTag().c_str(),
parent,data.length());
if (param->tag != tag)
return false;
data.cut(-tag.coding().length());
int len = ASNLib::decodeLength(data);
if (len < 0)
return false;
// TODO - should check Encoding Scheme at some point as also translation tables
XmlElement* enc = new XmlElement(param->name);
parent->addChild(enc);
if (addEnc)
enc->setAttribute(s_encAttr,"str");
String str;
decodeGSM7Bit(data,len,str);
enc->addText(str);
return true;
}
static void encodeGSM7Bit(const String& str, DataBlock& db)
{
if (!str.length())
return;
u_int8_t bits = 0;
for (unsigned int i = 0; i < str.length(); i++) {
if (bits == 7) {
bits = 0;
continue;
}
u_int8_t byte = 0x00;
byte |= (str[i] & 0x7f) >> bits;
if (i < str.length() - 1)
byte |= str[i + 1] << (7 - bits);
db.append(&byte,sizeof(byte));
bits++;
}
}
static bool encodeGSMString(const Parameter* param, MapCamelType* type, DataBlock& data, XmlElement* elem, int& err)
{
if (!(param && elem))
return false;
XDebug(&__plugin,DebugAll,"encodeGSMString(param=%s[%p],elem=%s[%p])",param->name.c_str(),param,elem->getTag().c_str(),elem);
if (elem->getTag() != param->name)
return false;
const String& str = elem->getText();
encodeGSM7Bit(str,data);
if (param->tag != s_noTag) {
data.insert(ASNLib::buildLength(data));
data.insert(param->tag.coding());
}
return true;
}
static bool decodeFlags(const Parameter* param, MapCamelType* type, AsnTag& tag, DataBlock& data, XmlElement* parent, bool addEnc, int& err)
{
if (!(param && type && data.length() && parent))
return false;
XDebug(&__plugin,DebugAll,"decodeFlags(param=%s[%p],elem=%s[%p],datalen=%d, data[0]=%d)",param->name.c_str(),param,
parent->getTag().c_str(),parent,data.length(),data[0]);
if (param->tag != tag)
return false;
data.cut(-tag.coding().length());
int len = ASNLib::decodeLength(data);
if (len <= 0)
return false;
XmlElement* child = new XmlElement(param->name);
parent->addChild(child);
if (addEnc)
child->setAttribute(s_encAttr,"str");
u_int8_t flags = data[0];
String str;
if (param->content) {
const SignallingFlags* list = static_cast<const SignallingFlags*>(param->content);
if (!list)
return false;
for (; list->mask; list++) {
if ((flags & list->mask) == list->value)
str.append(list->name,",");
}
}
data.cut(-len);
child->addText(str);
return true;
}
static bool encodeFlags(const Parameter* param, MapCamelType* type, DataBlock& data, XmlElement* elem, int& err)
{
if (!(param && elem))
return false;
XDebug(&__plugin,DebugAll,"encodeFlags(param=%s[%p],elem=%s[%p])",param->name.c_str(),param,elem->getTag().c_str(),elem);
u_int8_t byte = 0;
if (param->content) {
const SignallingFlags* flags = static_cast<const SignallingFlags*>(param->content);
if (!flags)
return false;
const String& text = elem->getText();
ObjList* list = text.split(',',false);
for (ObjList* o = list->skipNull(); o; o = o->skipNext()) {
String* s = static_cast<String*>(o->get());
const SignallingFlags* flag = flags;
for (; flag->mask && *s != flag->name; flag++);
if (!flag->name) {
DDebug(&__plugin,DebugAll,"encodeFlags '%s' not found",s->c_str());
continue;
}
byte |= flag->value;
}
TelEngine::destruct(list);
}
data.append(&byte,sizeof(byte));
if (param->tag != s_noTag) {
data.insert(ASNLib::buildLength(data));
data.insert(param->tag.coding());
}
return true;
}
static bool decodeString(const Parameter* param, MapCamelType* type, AsnTag& tag, DataBlock& data, XmlElement* parent, bool addEnc, int& err)
{
if (!(param && type && data.length() && parent))
return false;
XDebug(&__plugin,DebugAll,"decodeString(param=%s[%p],elem=%s[%p],datalen=%d, data[0]=%d)",param->name.c_str(),param,parent->getTag().c_str(),
parent,data.length(),data[0]);
if (param->tag != tag)
return false;
data.cut(-tag.coding().length());
String value;
int t = 0;
int len = ASNLib::decodeString(data,&value,&t,false);
if (len <= 0)
return false;
XmlElement* child = new XmlElement(param->name);
parent->addChild(child);
child->addText(value);
if (addEnc)
child->setAttribute(s_encAttr,"str");
return true;
}
static bool encodeString(const Parameter* param, MapCamelType* type, DataBlock& data, XmlElement* elem, int& err)
{
if (!(param && elem))
return false;
XDebug(&__plugin,DebugAll,"encodeString(param=%s[%p],elem=%s[%p])",param->name.c_str(),param,elem->getTag().c_str(),elem);
const String& text = elem->getText();
data.append(ASNLib::encodeString(text,ASNLib::PRINTABLE_STR,false));
if (param->tag != s_noTag) {
data.insert(ASNLib::buildLength(data));
data.insert(param->tag.coding());
}
return true;
}
static bool decodeBool(const Parameter* param, MapCamelType* type, AsnTag& tag, DataBlock& data, XmlElement* parent, bool addEnc, int& err)
{
if (!(param && type && data.length() && parent))
return false;
XDebug(&__plugin,DebugAll,"decodeBool(param=%s[%p],elem=%s[%p],datalen=%d, data[0]=%d)",param->name.c_str(),param,parent->getTag().c_str(),
parent,data.length(),data[0]);
if (param->tag != tag)
return false;
data.cut(-tag.coding().length());
bool value = false;
int len = ASNLib::decodeBoolean(data,&value,false);
if (len <= 0)
return false;
XmlElement* child = new XmlElement(param->name);
parent->addChild(child);
child->addText(String::boolText(value));
if (addEnc)
child->setAttribute(s_encAttr,"bool");
return true;
}
static bool encodeBool(const Parameter* param, MapCamelType* type, DataBlock& data, XmlElement* elem, int& err)
{
if (!(param && elem))
return false;
XDebug(&__plugin,DebugAll,"encodeBool(param=%s[%p],elem=%s[%p])",param->name.c_str(),param,elem->getTag().c_str(),elem);
bool val = elem->getText().toBoolean();
data.append(ASNLib::encodeBoolean(val,false));
if (param->tag != s_noTag) {
data.insert(ASNLib::buildLength(data));
data.insert(param->tag.coding());
}
return true;
}
// Nature of Address Indicator
static const TokenDict s_dict_nai[] = {
{ "subscriber", 1 },
{ "unknown", 2 },
{ "national", 3 },
{ "international", 4 },
{ "network-specific", 5 },
{ "national-routing", 6 },
{ "specific-routing", 7 },
{ "routing-with-cdn", 8 },
{ 0, 0 }
};
// Numbering Plan Indicator
static const TokenDict s_dict_numPlanIsup[] = {
{ "unknown", 0 },
{ "isdn", 1 },
{ "data", 3 },
{ "telex", 4 },
{ "private", 5 },
{ "national", 6 },
{ 0, 0 }
};
// Address Presentation
static const TokenDict s_dict_presentation[] = {
{ "allowed", 0 },
{ "restricted", 1 },
{ "unavailable", 2 },
// aliases for restrict=...
{ "no", 0 },
{ "false", 0 },
{ "yes", 1 },
{ "true", 1 },
{ 0, 0 }
};
// Screening Indicator
static const TokenDict s_dict_screening[] = {
{ "user-provided", 0 },
{ "user-provided-passed", 1 },
{ "user-provided-failed", 2 },
{ "network-provided", 3 },
// aliases for screened=...
{ "no", 0 },
{ "false", 0 },
{ "yes", 1 },
{ "true", 1 },
{ 0, 0 }
};
// Generic number qualifier
static const TokenDict s_dict_qual[] = {
{ "dialed-digits", 0 },
{ "called-additional", 1 },
{ "caller-failed", 2 },
{ "caller-not-screened", 3 },
{ "terminating", 4 },
{ "connected-additional", 5 },
{ "caller-additional", 6 },
{ "called-original", 7 },
{ "redirecting", 8 },
{ "redirection", 9 },
{ 0, 0 }
};
// Utility function - extract just ISUP digits from a parameter
static void getDigits(String& num, bool odd, const unsigned char* buf, unsigned int len)
{
static const char digits[] = "0123456789ABCD?.";
for (unsigned int i = 0; i < len; i++) {
num += digits[buf[i] & 0x0f];
if (odd && ((i+1) == len))
break;
num += digits[buf[i] >> 4];
}
}
// Utility function - write digit sequences
static void setDigits(DataBlock& data, const char* val, unsigned char nai, int b2 = -1, int b0 = -1)
{
unsigned char buf[32];
unsigned int len = 0;
if (b0 >= 0)
buf[len++] = b0 & 0xff;
unsigned int naiPos = len++;
buf[naiPos] = nai & 0x7f;
if (b2 >= 0)
buf[len++] = b2 & 0xff;
bool odd = false;
while (val && (len < sizeof(buf))) {
char c = *val++;
if (!c)
break;
unsigned char n = 0;
if (('0' <= c) && (c <= '9'))
n = c - '0';
else if ('.' == c)
n = 15;
else if ('A' == c)
n = 10;
else if ('B' == c)
n = 11;
else if ('C' == c)
n = 12;
else if ('D' == c)
n = 13;
else
continue;
odd = !odd;
if (odd)
buf[len] = n;
else
buf[len++] |= (n << 4);
}
if (odd) {
buf[naiPos] |= 0x80;
len++;
}
XDebug(&__plugin,DebugAll,"setDigits encoding %u octets (%s)",len,odd ? "odd" : "even");
data.append(buf,len);
}
static bool decodeCallNumber(const Parameter* param, MapCamelType* type, AsnTag& tag, DataBlock& data,
XmlElement* parent, bool addEnc, int& err)
{
if (!(param && type && data.length() && parent))
return false;
XDebug(&__plugin,DebugAll,"decodeCallNumber(param=%s[%p],elem=%s[%p],datalen=%d)",param->name.c_str(),param,
parent->getTag().c_str(),parent,data.length());
if (param->tag != tag)
return false;
data.cut(-tag.coding().length());
XmlElement* child = new XmlElement(param->name);
parent->addChild(child);
int len = ASNLib::decodeLength(data);
if (len < 2)
return false;
unsigned int index = 0;
unsigned char qualifier = 0;
if (type->type == TcapXApplication::GenericNumber) {
if (len < 3)
return false;
qualifier = data[index];
index++;
}
bool odd = (data[index] & 0x80) == 1;
unsigned char nai = data[index] & 0x7f;
index++;
unsigned char plan = (data[index] >> 4) & 7;
unsigned char pres = (data[index] >> 2) & 3;
unsigned char scrn = data[index] & 3;
if (type->type == TcapXApplication::GenericNumber)
child->setAttribute(s_qualifierAttr,lookup(qualifier,s_dict_qual,"unknown"));
child->setAttribute(s_natureAttr,lookup(nai,s_dict_nai,"unknown"));
child->setAttribute(s_planAttr,lookup(plan,s_dict_numPlanIsup,"unknown"));
if (plan == 1)
child->setAttribute(s_encAttr,"e164");
String tmp;
switch (type->type) {
case TcapXApplication::CalledPartyNumber:
case TcapXApplication::LocationNumber:
tmp = ((data[index] & 0x80) == 0);
child->setAttribute(s_innAttr,tmp);
break;
case TcapXApplication::CallingPartyNumber:
case TcapXApplication::GenericNumber:
tmp = ((data[index] & 0x80) == 0);
child->setAttribute(s_completeAttr,tmp);
break;
default:
break;
}
switch (type->type) {
case TcapXApplication::CallingPartyNumber:
case TcapXApplication::RedirectingNumber:
case TcapXApplication::OriginalCalledNumber:
case TcapXApplication::LocationNumber:
case TcapXApplication::GenericNumber:
child->setAttribute(s_restrictAttr,lookup(pres,s_dict_presentation));
default:
break;
}
switch (type->type) {
case TcapXApplication::CallingPartyNumber:
case TcapXApplication::LocationNumber:
case TcapXApplication::GenericNumber:
child->setAttribute(s_screenedtAttr,lookup(scrn,s_dict_screening));
default:
break;
}
index++;
String digits;
getDigits(digits,odd,data.data(index,len - index),len - index);
data.cut(-len);
child->addText(digits);
return true;
}
static bool encodeCallNumber(const Parameter* param, MapCamelType* type, DataBlock& data, XmlElement* elem, int& err)
{
if (!(param && elem))
return false;
XDebug(&__plugin,DebugAll,"encodeCallNumber(param=%s[%p],elem=%s[%p],datalen=%d)",param->name.c_str(),param,
elem->getTag().c_str(),elem,data.length());
unsigned char nai = lookup(elem->attribute(s_natureAttr),s_dict_nai,2) & 0x7f;
unsigned char plan = lookup(elem->attribute(s_planAttr),s_dict_numPlanIsup,1);
int b0 = -1;
if (type->type == TcapXApplication::GenericNumber) {
b0 = 0;
b0 = 0xff & (lookup(elem->attribute(s_qualifierAttr),s_dict_presentation));
}
// Numbering plan
unsigned char b2 = (plan & 7) << 4;
switch (type->type) {
case TcapXApplication::CalledPartyNumber:
case TcapXApplication::LocationNumber:
if (!TelEngine::null(elem->getAttribute(s_innAttr)) && !elem->getAttribute(s_innAttr)->toBoolean(true))
b2 |= 0x80;
break;
case TcapXApplication::CallingPartyNumber:
case TcapXApplication::GenericNumber:
if (!TelEngine::null(elem->getAttribute(s_completeAttr)) && !elem->getAttribute(s_completeAttr)->toBoolean(true))
b2 |= 0x80;
break;
default:
break;
}
switch (type->type) {
case TcapXApplication::CallingPartyNumber:
case TcapXApplication::RedirectingNumber:
case TcapXApplication::OriginalCalledNumber:
case TcapXApplication::LocationNumber:
case TcapXApplication::GenericNumber:
b2 |= (lookup(elem->attribute(s_restrictAttr),s_dict_presentation) & 3) << 2;
default:
break;
}
switch (param->type) {
case TcapXApplication::CallingPartyNumber:
case TcapXApplication::LocationNumber:
case TcapXApplication::GenericNumber:
b2 |= (lookup(elem->attribute(s_screenedtAttr),s_dict_screening) & 3);
default:
break;
}
const String& digits = elem->getText();
setDigits(data,digits,nai,b2,b0);
data.insert(ASNLib::buildLength(data));
data.insert(param->tag.coding());
return true;
}
// Redirection Information (Q,763 3.45) bits CBA
static const TokenDict s_dict_redir_main[] = {
{ "none", 0 },
{ "rerouted", 1 },
{ "rerouted-restrict-all", 2 },
{ "diverted", 3 },
{ "diverted-restrict-all", 4 },
{ "rerouted-restrict-number", 5 },
{ "diverted-restrict-number", 6 },
{ 0, 0 }
};
// Redirection Information (Q,763 3.45) bits HGFE or PONM
static const TokenDict s_dict_redir_reason[] = {
{ "busy", 1 },
{ "noanswer", 2 },
{ "always", 3 },
{ "deflected", 4 },
{ "diverted", 5 },
{ "offline", 6 },
{ 0, 0 }
};
static const String s_reasonOrigAttr = "reason_original";
static const String s_counterAttr = "counter";
static const String s_reasonAttr = "reason";
static bool decodeRedir(const Parameter* param, MapCamelType* type, AsnTag& tag, DataBlock& data,
XmlElement* parent, bool addEnc, int& err)
{
if (!(param && type && data.length() && parent))
return false;
XDebug(&__plugin,DebugAll,"decodeRedir(param=%s[%p],elem=%s[%p],datalen=%d)",param->name.c_str(),param,
parent->getTag().c_str(),parent,data.length());
if (param->tag != tag)
return false;
data.cut(-tag.coding().length());
XmlElement* child = new XmlElement(param->name);
parent->addChild(child);
int len = ASNLib::decodeLength(data);
if (len < 1)
return false;
// Redirecting indicator
unsigned char reason = data[0] & 0x07;
child->addText(lookup(reason,s_dict_redir_main,""));
// Original reason
reason = data[0] >> 4;
child->setAttribute(s_reasonOrigAttr,lookup(reason,s_dict_redir_reason));
if (len > 1) {
// Counter
int count = data[1] & 0x07;
if (count)
child->setAttribute(s_counterAttr,String(count));
// Reason
reason = data[1] >> 4;
if (reason)
child->setAttribute(s_reasonAttr,lookup(reason,s_dict_redir_reason));
}
if (addEnc)
child->setAttribute(s_encAttr,"str");
data.cut(-len);
return true;
}
static bool encodeRedir(const Parameter* param, MapCamelType* type, DataBlock& data, XmlElement* elem, int& err)
{
if (!(param && elem))
return false;
XDebug(&__plugin,DebugAll,"encodeCallNumber(param=%s[%p],elem=%s[%p],datalen=%d)",param->name.c_str(),param,
elem->getTag().c_str(),elem,data.length());
unsigned char b0 = lookup(elem->getText(),s_dict_redir_main,0) & 0x07;
b0 |= (lookup(elem->attribute(s_reasonOrigAttr),s_dict_redir_reason,0) & 0x0f) << 4;
data.append(&b0,sizeof(b0));
unsigned char b1 = String(elem->attribute(s_counterAttr)).toInteger() & 0x07;
b1 |= (lookup(elem->attribute(s_reasonAttr),s_dict_redir_reason,0) & 0x0f) << 4;
data.append(&b1,sizeof(b1));
data.insert(ASNLib::buildLength(data));
data.insert(param->tag.coding());
return true;
}
// Coding standard as defined in Q.931/Q.850
static const TokenDict s_dict_codingStandard[] = {
{"CCITT", 0x00},
{"ISO/IEC", 0x20},
{"national", 0x40},
{"network specific", 0x60},
{0,0}
};
// Q.931 4.5.5. Information transfer capability: Bits 0-4
// Defined for CCITT coding standard
static const TokenDict s_dict_transferCapCCITT[] = {
{"speech", 0x00}, // Speech
{"udi", 0x08}, // Unrestricted digital information
{"rdi", 0x09}, // Restricted digital information
{"3.1khz-audio", 0x10}, // 3.1 khz audio
{"udi-ta", 0x11}, // Unrestricted digital information with tone/announcements
{"video", 0x18}, // Video
{0,0}
};
// Q.931 4.5.5. Transfer mode: Bits 5,6
// Defined for CCITT coding standard
static const TokenDict s_dict_transferModeCCITT[] = {
{"circuit", 0x00}, // Circuit switch mode
{"packet", 0x40}, // Packet mode
{0,0}
};
// Q.931 4.5.5. Transfer rate: Bits 0-4
// Defined for CCITT coding standard
static const TokenDict s_dict_transferRateCCITT[] = {
{"packet", 0x00}, // Packet mode only
{"64kbit", 0x10}, // 64 kbit/s
{"2x64kbit", 0x11}, // 2x64 kbit/s
{"384kbit", 0x13}, // 384 kbit/s
{"1536kbit", 0x15}, // 1536 kbit/s
{"1920kbit", 0x17}, // 1920 kbit/s
{"multirate", 0x18}, // Multirate (64 kbit/s base rate)
{0,0}
};
// Q.931 4.5.5. User information Layer 1 protocol: Bits 0-4
// Defined for CCITT coding standard
static const TokenDict s_dict_formatCCITT[] = {
{"v110", 0x01}, // Recomendation V.110 and X.30
{"mulaw", 0x02}, // Recomendation G.711 mu-law
{"alaw", 0x03}, // Recomendation G.711 A-law
{"g721", 0x04}, // Recomendation G.721 32kbit/s ADPCM and I.460
{"h221", 0x05}, // Recomendation H.221 and H.242
{"non-CCITT", 0x07}, // Non CCITT standardized rate adaption
{"v120", 0x08}, // Recomendation V.120
{"x31", 0x09}, // Recomendation X.31 HDLC flag stuffing
{0,0}
};
static const String s_codingAttr = "coding";
static const String s_transferCapAttr = "transfercap";
static const String s_transferModeAttr = "transfermode";
static const String s_transferRateAttr = "transferrate";
static const String s_multiplierAttr = "multiplier";
static bool decodeUSI(const Parameter* param, MapCamelType* type, AsnTag& tag, DataBlock& data,
XmlElement* parent, bool addEnc, int& err)
{
if (!(param && type && data.length() && parent))
return false;
XDebug(&__plugin,DebugAll,"decodeUSI(param=%s[%p],elem=%s[%p],datalen=%d)",param->name.c_str(),param,
parent->getTag().c_str(),parent,data.length());
if (param->tag != tag)
return false;
data.cut(-tag.coding().length());
XmlElement* child = new XmlElement(param->name);
parent->addChild(child);
int len = ASNLib::decodeLength(data);
if (len < 2)
return false;
// Byte 0: Coding standard (bit 5,6), Information transfer capability (bit 0-4)
// Byte 1: Transfer mode (bit 5,6), Transfer rate (bit 0-4)
unsigned char coding = data[0] & 0x60;
child->setAttribute(s_codingAttr,lookup(coding,s_dict_codingStandard));
coding = data[0] & 0x1f;
child->setAttribute(s_transferCapAttr,lookup(coding,s_dict_transferCapCCITT));
coding = data[1] & 0x60;
child->setAttribute(s_transferModeAttr,lookup(coding,s_dict_transferModeCCITT));
u_int8_t rate = data[1] & 0x1f;
child->setAttribute(s_transferRateAttr,lookup(rate,s_dict_transferRateCCITT));
// Figure 4.11 Note 1: Next byte is the rate multiplier if the transfer rate is 'multirate' (0x18)
u_int8_t crt = 2;
if (rate == 0x18) {
if (len < 3) {
Debug(&__plugin,DebugMild,"decodeUSI(). Invalid length %u. No rate multiplier",len);
return false;
}
child->setAttribute(s_multiplierAttr,String(data[2] & 0x7f));
crt = 3;
}
if (len <= crt) {
data.cut(-len);
return true;
}
u_int8_t ident = (data[crt] & 0x60) >> 5;
if (ident != 1) {
Debug(&__plugin,DebugNote,"decodeUSI(). Invalid layer 1 ident %u",ident);
return true;
}
child->addText(lookup(data[crt] & 0x1f,s_dict_formatCCITT));
data.cut(-len);
return true;
}
static bool encodeUSI(const Parameter* param, MapCamelType* type, DataBlock& data, XmlElement* elem, int& err)
{
if (!(param && elem))
return false;
XDebug(&__plugin,DebugAll,"encodUSI(param=%s[%p],elem=%s[%p],datalen=%d)",param->name.c_str(),param,
elem->getTag().c_str(),elem,data.length());
u_int8_t buff[5] = {2,0x00,0x80,0x80,0x80};
unsigned char coding = lookup(elem->attribute(s_codingAttr),s_dict_codingStandard,0);
unsigned char cap = lookup(elem->attribute(s_transferCapAttr),s_dict_transferCapCCITT,0);
unsigned char mode = lookup(elem->attribute(s_transferModeAttr),s_dict_transferModeCCITT,0);
unsigned char rate = lookup(elem->attribute(s_transferRateAttr),s_dict_transferRateCCITT,0x10);
buff[1] = (coding & 0x60) | (cap & 0x1f);
buff[2] |= (mode & 0x60) | (rate & 0x1f);
if (rate == 0x18) {
buff[0] = 3;
rate = String(elem->attribute(s_multiplierAttr)).toInteger();
buff[3] |= rate & 0x7f;
}
// User information layer data
// Bit 7 = 1, Bits 5,6 = layer (1), Bits 0-4: the value
int format = lookup(elem->getText(),s_dict_formatCCITT,-1);
if (format != -1) {
buff[buff[0] + 1] |= 0x20 | (((unsigned char)format) & 0x1f);
buff[0]++;
}
data.assign(buff,buff[0] + 1);
data.insert(param->tag.coding());
return true;
}
static const Capability s_mapCapab[] = {
{"LocationManagement", {"updateLocation", "cancelLocation", "purgeMS", "updateGprsLocation", "anyTimeInterrogation", ""}},
{"Authentication", {"sendAuthenticationInfo", ""}},
{"SubscriberData", {"insertSubscriberData", "deleteSubscriberData", "restoreData", ""}},
{"Routing", {"sendRoutingInfoForGprs", "statusReport", ""}},
{"VLR-Routing", {"provideRoamingNumber", ""}},
{"TraceSubscriber", {"activateTraceMode", "deactivateTraceMode", ""}},
{"Services", {"registerSS", "eraseSS", "activateSS", "deactivateSS", "interrogateSS", "registerPassword", "getPassword",
"processUnstructuredSS-Request", "unstructuredSS-Request", "unstructuredSS-Notify", ""}},
{"Miscellaneous", {"sendIMSI", "readyForSM", "setReportingState", ""}},
{"ErrorRecovery", {"reset", "forwardCheckSS-Indication", "failureReport", ""}},
{"Charging", {""}},
{"SMSC", {"alertServiceCentre", "sendRoutingInfoForSM", ""}},
{0, {""}},
};
static const AppCtxt s_mapAppCtxt[]= {
// Network Loc Up context
{"networkLocUpContext-v3", "0.4.0.0.1.0.1.3", "updateLocation,forwardCheckSs,restoreData,insertSubscriberData,activateTraceMode"},
{"networkLocUpContext-v2", "0.4.0.0.1.0.1.2", "updateLocation,forwardCheckSs,restoreData,insertSubscriberData,activateTraceMode"},
{"networkLocUpContext-v1", "0.4.0.0.1.0.1.1", "updateLocation,forwardCheckSs,sendParameters,insertSubscriberData,activateTraceMode"},
// Location Cancellation context
{"locationCancelationContext-v3", "0.4.0.0.1.0.2.3", "cancelLocation"},
{"locationCancelationContext-v2", "0.4.0.0.1.0.2.2", "cancelLocation"},
{"locationCancelationContext-v1", "0.4.0.0.1.0.2.1", "cancelLocation"},
// Roaming Number Enquiry Context
{"roamingNumberEnquiryContext-v3", "0.4.0.0.1.0.3.3", "provideRoamingNumber"},
{"roamingNumberEnquiryContext-v2", "0.4.0.0.1.0.3.2", "provideRoamingNumber"},
{"roamingNumberEnquiryContext-v1", "0.4.0.0.1.0.3.1", "provideRoamingNumber"},
// Location Info Retrieval Context
{"locationInfoRetrievalContext-v3", "0.4.0.0.1.0.5.3", "sendRoutingInfo"},
{"locationInfoRetrievalContext-v2", "0.4.0.0.1.0.5.2", "sendRoutingInfo"},
{"locationInfoRetrievalContext-v1", "0.4.0.0.1.0.5.1", "sendRoutingInfo"},
// Reporting Context
{"reportingContext-v3", "0.4.0.0.1.0.7.3", "setReportingState,statusReport,remoteUserFree"},
// Info retrieval context
{"infoRetrievalPackage-v3", "0.4.0.0.1.0.14.3", "sendAuthenticationInfo"},
{"infoRetrievalContext-v2", "0.4.0.0.1.0.14.2", "sendAuthenticationInfo"},
{"infoRetrievalContext-v1", "0.4.0.0.1.0.14.1", "sendParameters"},
// Subscriber Data Management Context
{"subscriberDataMngtContext-v3", "0.4.0.0.1.0.16.3", "insertSubscriberData,deleteSubscriberData"},
{"subscriberDataMngtContext-v2", "0.4.0.0.1.0.16.2", "insertSubscriberData,deleteSubscriberData"},
{"subscriberDataMngtContext-v1", "0.4.0.0.1.0.16.1", "insertSubscriberData,deleteSubscriberData"},
// Tracing context
{"tracingContext-v3 ", "0.4.0.0.1.0.17.3", "activateTraceMode,deactivateTraceMode"},
{"tracingContext-v2 ", "0.4.0.0.1.0.17.2", "activateTraceMode,deactivateTraceMode"},
{"tracingContext-v1 ", "0.4.0.0.1.0.17.1", "activateTraceMode,deactivateTraceMode"},
// Network functional SS context
{"networkFunctionalSsContext-v2", "0.4.0.0.1.0.18.2", "registerSS,eraseSS,activateSS,deactivateSS,"
"interrogateSS,registerPassword,getPassword"},
{"networkFunctionalSsContext-v1", "0.4.0.0.1.0.18.1", "registerSS,eraseSS,activateSS,deactivateSS,"
"interrogateSS,registerPassword,getPassword"},
// Network unstructured SS context
{"networkUnstructuredSsContext-v2", "0.4.0.0.1.0.19.2", "processUnstructuredSS-Request,unstructuredSS-Request,unstructuredSS-Notify"},
{"networkUnstructuredSsContext-v1", "0.4.0.0.1.0.19.1", "processUnstructuredSS-Data"},
{"shortMsgGatewayContext-v3", "0.4.0.0.1.0.20.3", "sendRoutingInfoForSM"},
{"shortMsgGatewayContext-v2", "0.4.0.0.1.0.20.2", "sendRoutingInfoForSM"},
{"shortMsgGatewayContext-v1", "0.4.0.0.1.0.20.1", "sendRoutingInfoForSM"},
{"shortMsgAlertContext-v2", "0.4.0.0.1.0.23.2", "alertServiceCentre"},
{"shortMsgAlertContext-v1", "0.4.0.0.1.0.23.1", "alertServiceCentre"},
// MS Purging Context
{"msPurgingContext-v3", "0.4.0.0.1.0.27.3", "purgeMS"},
{"msPurgingContext-v2", "0.4.0.0.1.0.27.2", "purgeMS"},
// Any Time Info Enquiry Context
{"anyTimeInfoEnquiryContext-v3", "0.4.0.0.1.0.29.3", "anyTimeInterrogation"},
// GPRS Location Update Context
{"gprsLocationUpdateContext-v3", "0.4.0.0.1.0.32.3", "updateGprsLocation,insertSubscriberData,activateTraceMode"},
// GPRS Location Info Retrieval Context
{"gprsLocationInfoRetrievalContext-v3" , "0.4.0.0.1.0.33.3", "sendRoutingInfoForGprs"},
{"", "", ""},
};
static const AppCtxt s_camelAppCtxt[] = {
{"CAP-v2-gsmSSF-to-gsmSCF-AC", "0.4.0.0.1.0.50.1", "initialDP,establishTemporaryConnection,connectToResource,"
"disconnectForwardConnection,connect,releaseCall,eventReportBCSM,"
"requestReportBCSMEvent,applyChargingReport,applyCharging,continue,"
"resetTimer,furnishChargingInformation,callInformationReport,"
"callInformationRequest,sendChargingInformation,specializedResourceReport,"
"playAnnouncement,promptAndCollectUserInformation,cancel,activityTest"},
{"CAP-v2-assist-gsmSSF-to-gsmSCF-AC", "0.4.0.0.1.0.51.1", "assistRequestInstructions,disconnectForwardConnection,connectToResource,"
"resetTimer,specializedResourceReport,playAnnouncement,"
"promptAndCollectUserInformation,cancel,activityTest"},
{"CAP-v2-gsmSRF-to-gsmSCF-AC", "0.4.0.0.1.0.52.1", "assistRequestInstructions,specializedResourceReport,playAnnouncement,"
"promptAndCollectUserInformation,cancel,activityTest"},
{"", "", ""}
};
static const MapCamelType s_types[] = {
{TcapXApplication::Null, TcapXApplication::NullEnc, decodeNull, encodeNull},
{TcapXApplication::Integer, TcapXApplication::IntEnc, decodeInt, encodeInt},
{TcapXApplication::OID, TcapXApplication::OIDEnc, decodeOID, encodeOID},
{TcapXApplication::TBCD, TcapXApplication::StringEnc, decodeTBCD, encodeTBCD},
{TcapXApplication::AddressString, TcapXApplication::TelephonyEnc, decodeTel, encodeTel},
{TcapXApplication::HexString, TcapXApplication::HexEnc, decodeHex, encodeHex},
{TcapXApplication::Sequence, TcapXApplication::NoEnc, decodeSeq, encodeSeq},
{TcapXApplication::SequenceOf, TcapXApplication::NoEnc, decodeSeqOf, encodeSeqOf},
// for now, use the same encoder/decoder as SequenceOf, TODO - if needed,replace it
{TcapXApplication::SetOf, TcapXApplication::NoEnc, decodeSeqOf, encodeSeqOf},
{TcapXApplication::Choice, TcapXApplication::NoEnc, decodeChoice, encodeChoice},
{TcapXApplication::Enumerated, TcapXApplication::NoEnc, decodeEnumerated, encodeEnumerated},
{TcapXApplication::GSMString, TcapXApplication::StringEnc, decodeGSMString, encodeGSMString},
{TcapXApplication::BitString, TcapXApplication::HexEnc, decodeBitString, encodeBitString},
{TcapXApplication::Flags, TcapXApplication::StringEnc, decodeFlags, encodeFlags},
{TcapXApplication::AppString, TcapXApplication::StringEnc, decodeString, encodeString},
{TcapXApplication::Bool, TcapXApplication::BoolEnc, decodeBool, encodeBool},
{TcapXApplication::CellIdFixedLength, TcapXApplication::StringEnc, decodeTBCD, encodeTBCD},
{TcapXApplication::LAIFixedLength, TcapXApplication::StringEnc, decodeTBCD, encodeTBCD},
{TcapXApplication::CalledPartyNumber, TcapXApplication::TelephonyEnc, decodeCallNumber, encodeCallNumber},
{TcapXApplication::CallingPartyNumber, TcapXApplication::TelephonyEnc, decodeCallNumber, encodeCallNumber},
{TcapXApplication::LocationNumber, TcapXApplication::TelephonyEnc, decodeCallNumber, encodeCallNumber},
{TcapXApplication::OriginalCalledNumber, TcapXApplication::TelephonyEnc, decodeCallNumber, encodeCallNumber},
{TcapXApplication::RedirectingNumber, TcapXApplication::TelephonyEnc, decodeCallNumber, encodeCallNumber},
{TcapXApplication::GenericNumber, TcapXApplication::TelephonyEnc, decodeCallNumber, encodeCallNumber},
{TcapXApplication::ChargeNumber, TcapXApplication::TelephonyEnc, decodeCallNumber, encodeCallNumber},
{TcapXApplication::RedirectionInformation, TcapXApplication::StringEnc, decodeRedir, encodeRedir},
{TcapXApplication::UserServiceInfo, TcapXApplication::NoEnc, decodeUSI, encodeUSI},
// TODO High Layer Compatibility encode/decode implementation - see User teleservice information (Q.763 3.59)
{TcapXApplication::HiLayerCompat, TcapXApplication::NoEnc, decodeHex, encodeHex},
{TcapXApplication::None, TcapXApplication::NoEnc, 0, 0},
};
static const MapCamelType* findType(TcapXApplication::ParamType type)
{
const MapCamelType* t = s_types;
while (t->type != TcapXApplication::None) {
if (t->type == type)
return t;
t++;
}
return 0;
}
static const AsnTag s_ctxtPrim_0_Tag(AsnTag::Context, AsnTag::Primitive, 0);
static const AsnTag s_ctxtPrim_1_Tag(AsnTag::Context, AsnTag::Primitive, 1);
static const AsnTag s_ctxtPrim_2_Tag(AsnTag::Context, AsnTag::Primitive, 2);
static const AsnTag s_ctxtPrim_3_Tag(AsnTag::Context, AsnTag::Primitive, 3);
static const AsnTag s_ctxtPrim_4_Tag(AsnTag::Context, AsnTag::Primitive, 4);
static const AsnTag s_ctxtPrim_5_Tag(AsnTag::Context, AsnTag::Primitive, 5);
static const AsnTag s_ctxtPrim_6_Tag(AsnTag::Context, AsnTag::Primitive, 6);
static const AsnTag s_ctxtPrim_7_Tag(AsnTag::Context, AsnTag::Primitive, 7);
static const AsnTag s_ctxtPrim_8_Tag(AsnTag::Context, AsnTag::Primitive, 8);
static const AsnTag s_ctxtPrim_9_Tag(AsnTag::Context, AsnTag::Primitive, 9);
static const AsnTag s_ctxtPrim_10_Tag(AsnTag::Context, AsnTag::Primitive, 10);
static const AsnTag s_ctxtPrim_11_Tag(AsnTag::Context, AsnTag::Primitive, 11);
static const AsnTag s_ctxtPrim_12_Tag(AsnTag::Context, AsnTag::Primitive, 12);
static const AsnTag s_ctxtPrim_13_Tag(AsnTag::Context, AsnTag::Primitive, 13);
static const AsnTag s_ctxtPrim_15_Tag(AsnTag::Context, AsnTag::Primitive, 15);
static const AsnTag s_ctxtPrim_16_Tag(AsnTag::Context, AsnTag::Primitive, 16);
static const AsnTag s_ctxtPrim_17_Tag(AsnTag::Context, AsnTag::Primitive, 17);
static const AsnTag s_ctxtPrim_18_Tag(AsnTag::Context, AsnTag::Primitive, 18);
static const AsnTag s_ctxtPrim_19_Tag(AsnTag::Context, AsnTag::Primitive, 19);
static const AsnTag s_ctxtPrim_20_Tag(AsnTag::Context, AsnTag::Primitive, 20);
static const AsnTag s_ctxtPrim_21_Tag(AsnTag::Context, AsnTag::Primitive, 21);
static const AsnTag s_ctxtPrim_23_Tag(AsnTag::Context, AsnTag::Primitive, 23);
static const AsnTag s_ctxtPrim_25_Tag(AsnTag::Context, AsnTag::Primitive, 25);
static const AsnTag s_ctxtPrim_27_Tag(AsnTag::Context, AsnTag::Primitive, 27);
static const AsnTag s_ctxtPrim_28_Tag(AsnTag::Context, AsnTag::Primitive, 28);
static const AsnTag s_ctxtPrim_29_Tag(AsnTag::Context, AsnTag::Primitive, 29);
static const AsnTag s_ctxtPrim_30_Tag(AsnTag::Context, AsnTag::Primitive, 30);
static const AsnTag s_ctxtPrim_50_Tag(AsnTag::Context, AsnTag::Primitive, 50);
static const AsnTag s_ctxtPrim_51_Tag(AsnTag::Context, AsnTag::Primitive, 51);
static const AsnTag s_ctxtPrim_52_Tag(AsnTag::Context, AsnTag::Primitive, 52);
static const AsnTag s_ctxtPrim_53_Tag(AsnTag::Context, AsnTag::Primitive, 53);
static const AsnTag s_ctxtPrim_54_Tag(AsnTag::Context, AsnTag::Primitive, 54);
static const AsnTag s_ctxtPrim_55_Tag(AsnTag::Context, AsnTag::Primitive, 55);
static const AsnTag s_ctxtPrim_56_Tag(AsnTag::Context, AsnTag::Primitive, 56);
static const AsnTag s_ctxtPrim_57_Tag(AsnTag::Context, AsnTag::Primitive, 57);
static const AsnTag s_ctxtPrim_58_Tag(AsnTag::Context, AsnTag::Primitive, 58);
static const AsnTag s_ctxtCstr_0_Tag(AsnTag::Context, AsnTag::Constructor, 0);
static const AsnTag s_ctxtCstr_1_Tag(AsnTag::Context, AsnTag::Constructor, 1);
static const AsnTag s_ctxtCstr_2_Tag(AsnTag::Context, AsnTag::Constructor, 2);
static const AsnTag s_ctxtCstr_3_Tag(AsnTag::Context, AsnTag::Constructor, 3);
static const AsnTag s_ctxtCstr_4_Tag(AsnTag::Context, AsnTag::Constructor, 4);
static const AsnTag s_ctxtCstr_5_Tag(AsnTag::Context, AsnTag::Constructor, 5);
static const AsnTag s_ctxtCstr_6_Tag(AsnTag::Context, AsnTag::Constructor, 6);
static const AsnTag s_ctxtCstr_7_Tag(AsnTag::Context, AsnTag::Constructor, 7);
static const AsnTag s_ctxtCstr_8_Tag(AsnTag::Context, AsnTag::Constructor, 8);
static const AsnTag s_ctxtCstr_9_Tag(AsnTag::Context, AsnTag::Constructor, 9);
static const AsnTag s_ctxtCstr_10_Tag(AsnTag::Context, AsnTag::Constructor, 10);
static const AsnTag s_ctxtCstr_11_Tag(AsnTag::Context, AsnTag::Constructor, 11);
static const AsnTag s_ctxtCstr_12_Tag(AsnTag::Context, AsnTag::Constructor, 12);
static const AsnTag s_ctxtCstr_13_Tag(AsnTag::Context, AsnTag::Constructor, 13);
static const AsnTag s_ctxtCstr_14_Tag(AsnTag::Context, AsnTag::Constructor, 14);
static const AsnTag s_ctxtCstr_15_Tag(AsnTag::Context, AsnTag::Constructor, 15);
static const AsnTag s_ctxtCstr_16_Tag(AsnTag::Context, AsnTag::Constructor, 16);
static const AsnTag s_ctxtCstr_21_Tag(AsnTag::Context, AsnTag::Constructor, 21);
static const AsnTag s_ctxtCstr_22_Tag(AsnTag::Context, AsnTag::Constructor, 22);
static const AsnTag s_ctxtCstr_23_Tag(AsnTag::Context, AsnTag::Constructor, 23);
static const AsnTag s_ctxtCstr_24_Tag(AsnTag::Context, AsnTag::Constructor, 24);
static const AsnTag s_ctxtCstr_25_Tag(AsnTag::Context, AsnTag::Constructor, 25);
static const AsnTag s_ctxtCstr_27_Tag(AsnTag::Context, AsnTag::Constructor, 27);
static const AsnTag s_ctxtCstr_28_Tag(AsnTag::Context, AsnTag::Constructor, 28);
static const AsnTag s_ctxtCstr_29_Tag(AsnTag::Context, AsnTag::Constructor, 29);
static const AsnTag s_ctxtCstr_30_Tag(AsnTag::Context, AsnTag::Constructor, 30);
static const AsnTag s_ctxtCstr_50_Tag(AsnTag::Context, AsnTag::Constructor, 50);
static const AsnTag s_ctxtCstr_57_Tag(AsnTag::Context, AsnTag::Constructor, 57);
static const AsnTag s_ctxtCstr_59_Tag(AsnTag::Context, AsnTag::Constructor, 59);
static const TokenDict s_camelPhases[] = {
{"phase1", 1},
{"phase2", 2},
{0,0},
};
static const Parameter s_vlrCapability[] = {
{"supportedCamelPhases", s_ctxtPrim_0_Tag, true, TcapXApplication::BitString, s_camelPhases},
{"extensionContainer", s_sequenceTag, true, TcapXApplication::HexString, 0},
{"solsaSupportIndicator", s_nullTag, true, TcapXApplication::Null, 0},
{"", s_noTag, false,TcapXApplication::None, 0},
};
static const Parameter s_imsiWithLmsi[] = {
{"imsi", s_hexTag, false, TcapXApplication::TBCD, 0},
{"lmsi", s_hexTag, false, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_mapIdentity[] = {
{"imsi", s_hexTag, false, TcapXApplication::TBCD, 0},
{"imsi-WithLMSI", s_sequenceTag, false, TcapXApplication::Sequence, s_imsiWithLmsi},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_cancellationType[] = {
{"updateProcedure", 0x00},
{"subscriptionWithdraw", 0x01},
{0,0},
};
static const TokenDict s_protocolId[] = {
{"gsm-0408", 0x01},
{"gsm-0806", 0x02},
{"gsm-BSSMAP", 0x03},
{"ets-300102-1",0x04},
{0,0},
};
static const Parameter s_externalSignalInfo[] = {
{"protocolId", s_enumTag, false, TcapXApplication::Enumerated, s_protocolId},
{"signalInfo", s_hexTag, false, TcapXApplication::HexString, 0},
{"extensionContainer",s_sequenceTag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_alertPattern[] = {
{"alertingLevel-0", 0x00},
{"alertingLevel-1", 0x01},// AlertingPattern ::= '00000001'B
{"alertingLevel-2", 0x02},// AlertingPattern ::= '00000010'B
{"alertingCategory-1", 0x04},// AlertingPattern ::= '00000100'B
{"alertingCategory-2", 0x05},// AlertingPattern ::= '00000101'B
{"alertingCategory-3", 0x06},// AlertingPattern ::= '00000110'B
{"alertingCategory-4", 0x07},// AlertingPattern ::= '00000111'B
{"alertingCategory-5", 0x08},// AlertingPattern ::= '00001000'B
{0,0},
};
static const TokenDict s_extProtocolId[] = {
{"ets-300356", 0x01},
{0,0},
};
static const Parameter s_extExtenalSignalInfo[] = {
{"ext-protocolId", s_enumTag, false, TcapXApplication::Enumerated, s_extProtocolId},
{"signalInfo", s_hexTag, false, TcapXApplication::HexString, 0},
{"extensionContainer",s_sequenceTag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_category[] = {
{ "unknown", 0x00 }, // calling party's category is unknown
{ "operator-FR", 0x01 }, // operator, language French
{ "operator-EN", 0x02 }, // operator, language English
{ "operator-DE", 0x03 }, // operator, language German
{ "operator-RU", 0x04 }, // operator, language Russian
{ "operator-ES", 0x05 }, // operator, language Spanish
{ "ordinary", 0x0a }, // ordinary calling subscriber
{ "priority", 0x0b }, // calling subscriber with priority
{ "data", 0x0c }, // data call (voice band data)
{ "test", 0x0d }, // test call
{ "payphone", 0x0f }, // payphone
{ 0, 0 },
};
static const TokenDict s_subscriberStatus[] = {
{"serviceGranted", 0x00},
{"operatorDeterminedBarring", 0x01},
{0,0},
};
static const TokenDict s_SSCode[] = {
// TS 100 974 v7.15.0 page 321
{"allSS", 0x00}, // SS-Code ::= '00000000'B -- all SS
{"allLineIdentificationSS", 0x10}, // SS-Code ::= '00010000'B -- all line identification SS
{"clip", 0x11}, // SS-Code ::= '00010001'B -- calling line identification presentation
{"clir", 0x12}, // SS-Code ::= '00010010'B -- calling line identification restriction
{"colp", 0x13}, // SS-Code ::= '00010011'B -- connected line identification presentation
{"colr", 0x14}, // SS-Code ::= '00010100'B -- connected line identification restriction
{"mci", 0x15}, // SS-Code ::= '00010101'B -- malicious call identification
{"allNameIdentificationSS", 0x18}, // SS-Code ::= '00011000'B -- all name identification SS
{"cnap", 0x19}, // SS-Code ::= '00011001'B -- calling name presentation
{"allForwardingSS", 0x20}, // SS-Code ::= '00100000'B -- all forwarding SS
{"cfu", 0x21}, // SS-Code ::= '00100001'B -- call forwarding unconditional
{"allCondForwardingSS", 0x28}, // SS-Code ::= '00101000'B -- all conditional forwarding SS
{"cfb", 0x29}, // SS-Code ::= '00101001'B -- call forwarding on mobile subscriber busy
{"cfnry", 0x2a}, // SS-Code ::= '00101010'B -- call forwarding on no reply
{"cfnrc", 0x2b}, // SS-Code ::= '00101011'B -- call forwarding on mobile subscriber not reachable
{"cd", 0x24}, // SS-Code ::= '00100100'B -- call deflection
{"allCallOfferingSS", 0x30}, // SS-Code ::= '00110000'B -- all call offering SS includes also all forwarding SS
{"ect", 0x31}, // SS-Code ::= '00110001'B -- explicit call transfer
{"mah", 0x32}, // SS-Code ::= '00110010'B -- mobile access hunting
{"allCallCompletionSS", 0x40}, // SS-Code ::= '01000000'B -- all Call completion SS
{"cw", 0x41}, // SS-Code ::= '01000001'B -- call waiting
{"hold", 0x42}, // SS-Code ::= '01000010'B -- call hold
{"ccbs-A", 0x43}, // SS-Code ::= '01000011'B -- completion of call to busy subscribers, originating side
{"ccbs-B", 0x44}, // SS-Code ::= '01000100'B -- completion of call to busy subscribers, destination side
{"allMultiPartySS", 0x50}, // SS-Code ::= '01010000'B -- all multiparty SS
{"multiPTY", 0x51}, // SS-Code ::= '01010001'B -- multiparty
{"allCommunityOfInterest-SS", 0x60}, // SS-Code ::= '01100000'B -- all community of interest SS
{"cug", 0x61}, // SS-Code ::= '01100001'B -- closed user group
{"allChargingSS", 0x70}, // SS-Code ::= '01110000'B -- all charging SS
{"aoci", 0x71}, // SS-Code ::= '01110001'B -- advice of charge information
{"aocc", 0x72}, // SS-Code ::= '01110010'B -- advice of charge charging
{"allAdditionalInfoTransferSS",0x80}, // SS-Code ::= '10000000'B -- all additional information transfer SS
{"uus1", 0x81}, // SS-Code ::= '10000001'B -- UUS1 user-to-user signalling
{"uus2", 0x82}, // SS-Code ::= '10000010'B -- UUS2 user-to-user signalling
{"uus3", 0x83}, // SS-Code ::= '10000011'B -- UUS3 user-to-user signalling
{"allBarringSS", 0x90}, // SS-Code ::= '10010000'B -- all barring SS
{"barringOfOutgoingCalls", 0x91}, // SS-Code ::= '10010001'B -- barring of outgoing calls
{"baoc", 0x92}, // SS-Code ::= '10010010'B -- barring of all outgoing calls
{"boic", 0x93}, // SS-Code ::= '10010011'B -- barring of outgoing international calls
{"boicExHC", 0x94}, // SS-Code ::= '10010100'B -- barring of outgoing international calls except those directed to the home PLMN
{"barringOfIncomingCalls", 0x99}, // SS-Code ::= '10011001'B -- barring of incoming calls
{"baic", 0x9a}, // SS-Code ::= '10011010'B -- barring of all incoming calls
{"bicRoam", 0x24}, // SS-Code ::= '10011011'B -- barring of incoming calls when roaming outside home PLMN Country
{"allPLMN-specificSS", 0xf0}, // SS-Code ::= '11110000'B
{"plmn-specificSS-1", 0xf1}, // SS-Code ::= '11110001'B
{"plmn-specificSS-2", 0xf2}, // SS-Code ::= '11110010'B
{"plmn-specificSS-3", 0xf3}, // SS-Code ::= '11110011'B
{"plmn-specificSS-4", 0xf4}, // SS-Code ::= '11110100'B
{"plmn-specificSS-5", 0xf5}, // SS-Code ::= '11110101'B
{"plmn-specificSS-6", 0xf6}, // SS-Code ::= '11110110'B
{"plmn-specificSS-7", 0xf7}, // SS-Code ::= '11110111'B
{"plmn-specificSS-8", 0xf8}, // SS-Code ::= '11111000'B
{"plmn-specificSS-9", 0xf9}, // SS-Code ::= '11111001'B
{"plmn-specificSS-A", 0xfa}, // SS-Code ::= '11111010'B
{"plmn-specificSS-B", 0xfb}, // SS-Code ::= '11111011'B
{"plmn-specificSS-C", 0xfc}, // SS-Code ::= '11111100'B
{"plmn-specificSS-D", 0xfd}, // SS-Code ::= '11111101'B
{"plmn-specificSS-E", 0xfe}, // SS-Code ::= '11111110'B
{"plmn-specificSS-F", 0xff}, // SS-Code ::= '11111111'B
{"allCallPrioritySS", 0xa0}, // SS-Code ::= '10100000'B -- all call priority SS
{"emlpp", 0xa1}, // SS-Code ::= '10100001'B -- enhanced Multilevel Precedence Pre-emption (EMLPP) service
{"allLCSPrivacyException", 0xb0}, // SS-Code ::= '10110000'B -- all LCS Privacy Exception Classes
{"universal", 0xb1}, // SS-Code ::= '10110001'B -- allow location by any LCS client
{"callrelated", 0xb2}, // SS-Code ::= '10110010'B -- allow location by any value added LCS client to which a call
// -- is established from the target MS
{"callunrelated", 0xb3}, // SS-Code ::= '10110011'B -- allow location by designated external value added LCS clients
{"plmnoperator", 0xb4}, // SS-Code ::= '10110100'B -- allow location by designated PLMN operator LCS clients
{"allMOLR-SS", 0xc0}, // SS-Code ::= '11000000'B -- all Mobile Originating Location Request Classes
{"basicSelfLocation", 0xc1}, // SS-Code ::= '11000001'B -- allow an MS to request its own location
{"autonomousSelfLocation", 0xc2}, // SS-Code ::= '11000010'B -- allow an MS to perform self location without interaction
// -- with the PLMN for a predetermined period of time
{"transferToThirdParty", 0xc3}, // SS-Code ::= '11000011'B -- allow an MS to request transfer of its location to another LCS client
{0,0},
};
static const TokenDict s_bearerServiceCode[] = {
{"allBearerServices", 0x00}, // BearerServiceCode ::= '00000000'B
{"allDataCDA-Services", 0x10}, // BearerServiceCode ::= '00010000'B
{"dataCDA-300bps", 0x11}, // BearerServiceCode ::= '00010001'B
{"dataCDA-1200bps", 0x12}, // BearerServiceCode ::= '00010010'B
{"dataCDA-1200-75bps", 0x13}, // BearerServiceCode ::= '00010011'B
{"dataCDA-2400bps", 0x14}, // BearerServiceCode ::= '00010100'B
{"dataCDA-4800bps", 0x15}, // BearerServiceCode ::= '00010101'B
{"dataCDA-9600bps", 0x16}, // BearerServiceCode ::= '00010110'B
{"general-dataCDA", 0x17}, // BearerServiceCode ::= '00010111'B
{"allDataCDS-Services", 0x18}, // BearerServiceCode ::= '00011000'B
{"dataCDS-1200bps", 0x1a}, // BearerServiceCode ::= '00011010'B
{"dataCDS-2400bps", 0x1c}, // BearerServiceCode ::= '00011100'B
{"dataCDS-4800bps", 0x1d}, // BearerServiceCode ::= '00011101'B
{"dataCDS-9600bps", 0x1e}, // BearerServiceCode ::= '00011110'B
{"general-dataCDS", 0x1f}, // BearerServiceCode ::= '00011111'B
{"allPadAccessCA-Services",0x20}, // BearerServiceCode ::= '00100000'B
{"padAccessCA-300bps", 0x21}, // BearerServiceCode ::= '00100001'B
{"padAccessCA-1200bps", 0x22}, // BearerServiceCode ::= '00100010'B
{"padAccessCA-1200-75bps", 0x23}, // BearerServiceCode ::= '00100011'B
{"padAccessCA-2400bps", 0x24}, // BearerServiceCode ::= '00100100'B
{"padAccessCA-4800bps", 0x25}, // BearerServiceCode ::= '00100101'B
{"padAccessCA-9600bps", 0x26}, // BearerServiceCode ::= '00100110'B
{"general-padAccessCA", 0x27}, // BearerServiceCode ::= '00100111'B
{"allDataPDS-Services", 0x28}, // BearerServiceCode ::= '00101000'B
{"dataPDS-2400bps", 0x2c}, // BearerServiceCode ::= '00101100'B
{"dataPDS-4800bps", 0x2d}, // BearerServiceCode ::= '00101101'B
{"dataPDS-9600bps", 0x2e}, // BearerServiceCode ::= '00101110'B
{"general-dataPDS", 0x2f}, // BearerServiceCode ::= '00101111'B
{"allAlternateSpeech-DataCDA", 0x30}, // BearerServiceCode ::= '00110000'B
{"allAlternateSpeech-DataCDS", 0x38}, // BearerServiceCode ::= '00111000'B
{"allSpeechFollowedByDataCDA", 0x40}, // BearerServiceCode ::= '01000000'B
{"allSpeechFollowedByDataCDS", 0x48}, // BearerServiceCode ::= '01001000'B
{"allDataCircuitAsynchronous", 0x50}, // BearerServiceCode ::= '01010000'B
{"allAsynchronousServices", 0x60}, // BearerServiceCode ::= '01100000'B
{"allDataCircuitSynchronous", 0x58}, // BearerServiceCode ::= '01011000'B
{"allSynchronousServices", 0x68}, // BearerServiceCode ::= '01101000'B
{"allPLMN-specificBS", 0xd0}, // BearerServiceCode ::= '11010000'B
{"plmn-specificBS-1", 0xd1}, // BearerServiceCode ::= '11010001'B
{"plmn-specificBS-2", 0xd2}, // BearerServiceCode ::= '11010010'B
{"plmn-specificBS-3", 0xd3}, // BearerServiceCode ::= '11010011'B
{"plmn-specificBS-4", 0xd4}, // BearerServiceCode ::= '11010100'B
{"plmn-specificBS-5", 0xd5}, // BearerServiceCode ::= '11010101'B
{"plmn-specificBS-6", 0xd6}, // BearerServiceCode ::= '11010110'B
{"plmn-specificBS-7", 0xd7}, // BearerServiceCode ::= '11010111'B
{"plmn-specificBS-8", 0xd8}, // BearerServiceCode ::= '11011000'B
{"plmn-specificBS-9", 0xd9}, // BearerServiceCode ::= '11011001'B
{"plmn-specificBS-A", 0xda}, // BearerServiceCode ::= '11011010'B
{"plmn-specificBS-B", 0xdb}, // BearerServiceCode ::= '11011011'B
{"plmn-specificBS-C", 0xdc}, // BearerServiceCode ::= '11011100'B
{"plmn-specificBS-D", 0xdd}, // BearerServiceCode ::= '11011101'B
{"plmn-specificBS-E", 0xde}, // BearerServiceCode ::= '11011110'B
{"plmn-specificBS-F", 0xdf}, // BearerServiceCode ::= '11011111'B
{0,0},
};
static const TokenDict s_teleserviceCode[] = {
{"allTeleservices", 0x00}, // TeleserviceCode ::= '00000000'B
{"allSpeechTransmissionServices", 0x10}, // TeleserviceCode ::= '00010000'B
{"telephony", 0x11}, // TeleserviceCode ::= '00010001'B
{"emergencyCalls", 0x12}, // TeleserviceCode ::= '00010010'B
{"allShortMessageServices", 0x20}, // TeleserviceCode ::= '00100000'B
{"shortMessageMT-PP", 0x21}, // TeleserviceCode ::= '00100001'B
{"shortMessageMO-PP", 0x22}, // TeleserviceCode ::= '00100010'B
{"allFacsimileTransmissionServices", 0x60}, // TeleserviceCode ::= '01100000'B
{"facsimileGroup3AndAlterSpeech", 0x61}, // TeleserviceCode ::= '01100001'B
{"automaticFacsimileGroup3", 0x62}, // TeleserviceCode ::= '01100010'B
{"facsimileGroup4", 0x63}, // TeleserviceCode ::= '01100011'B
{"allDataTeleservices", 0x70}, // TeleserviceCode ::= '01110000'B
{"allTeleservices-ExeptSMS", 0x80}, // TeleserviceCode ::= '10000000'B
{"allVoiceGroupCallServices", 0x90}, // TeleserviceCode ::= '10010000'B
{"voiceGroupCall", 0x91}, // TeleserviceCode ::= '10010001'B
{"voiceBroadcastCall", 0x92}, // TeleserviceCode ::= '10010010'B
{"allPLMN-specificTS", 0xd0}, // TeleserviceCode ::= '11010000'B
{"plmn-specificTS-1", 0xd1}, // TeleserviceCode ::= '11010001'B
{"plmn-specificTS-2", 0xd2}, // TeleserviceCode ::= '11010010'B
{"plmn-specificTS-3", 0xd3}, // TeleserviceCode ::= '11010011'B
{"plmn-specificTS-4", 0xd4}, // TeleserviceCode ::= '11010100'B
{"plmn-specificTS-5", 0xd5}, // TeleserviceCode ::= '11010101'B
{"plmn-specificTS-6", 0xd6}, // TeleserviceCode ::= '11010110'B
{"plmn-specificTS-7", 0xd7}, // TeleserviceCode ::= '11010111'B
{"plmn-specificTS-8", 0xd8}, // TeleserviceCode ::= '11011000'B
{"plmn-specificTS-9", 0xd9}, // TeleserviceCode ::= '11011001'B
{"plmn-specificTS-A", 0xda}, // TeleserviceCode ::= '11011010'B
{"plmn-specificTS-B", 0xdb}, // TeleserviceCode ::= '11011011'B
{"plmn-specificTS-C", 0xdc}, // TeleserviceCode ::= '11011100'B
{"plmn-specificTS-D", 0xdd}, // TeleserviceCode ::= '11011101'B
{"plmn-specificTS-E", 0xde}, // TeleserviceCode ::= '11011110'B
{"plmn-specificTS-F", 0xdf}, // TeleserviceCode ::= '11011111'B
{0,0},
};
static const Parameter s_extBearerServiceCode[] = {
{"ext-BearerServiceCode", s_hexTag, false, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_extTeleserviceCode[] = {
{"ext-TeleserviceCode", s_hexTag, false, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_bearerService[] = {
{"bearerService", s_hexTag, false, TcapXApplication::Enumerated, s_bearerServiceCode},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_teleservice[] = {
{"teleservice", s_hexTag, false, TcapXApplication::Enumerated, s_teleserviceCode},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_basicServiceCode[] = {
{"bearerService", s_ctxtPrim_2_Tag, false, TcapXApplication::Enumerated, s_bearerServiceCode},
{"teleservice", s_ctxtPrim_3_Tag, false, TcapXApplication::Enumerated, s_teleserviceCode},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_extBasicServiceCode[] = {
{"ext-BearerService", s_ctxtPrim_2_Tag, false, TcapXApplication::HexString, 0},
{"ext-Teleservice", s_ctxtPrim_3_Tag, false, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const SignallingFlags s_forwardOptions[] = {
{ 0x80, 0x80, "notify-called" },
{ 0x40, 0x40, "presentation" },
{ 0x20, 0x20, "notify-caller" },
{ 0xc0, 0x00, "offline" },
{ 0xc1, 0xc1, "busy" },
{ 0xc2, 0xc2, "noanswer" },
{ 0xc3, 0xc3, "always" },
{ 0, 0, 0 },
};
static const SignallingFlags s_ssStatus[] = {
{ 0x01, 0x01, "active" },
{ 0x02, 0x02, "registered" },
{ 0x04, 0x04, "provisioned" },
{ 0x08, 0x08, "quiescent" },
{ 0, 0, 0 },
};
static const Parameter s_forwFeatureSeq[] = {
{"basicService", s_noTag, true, TcapXApplication::Choice, s_basicServiceCode},
{"ss-Status", s_ctxtPrim_4_Tag, false, TcapXApplication::Flags, s_ssStatus},
{"forwardedToNumber", s_ctxtPrim_5_Tag, true, TcapXApplication::AddressString, 0},
{"forwardedToSubaddress", s_ctxtPrim_8_Tag, true, TcapXApplication::HexString, 0},
{"forwardingOptions", s_ctxtPrim_6_Tag, true, TcapXApplication::Flags, s_forwardOptions},
{"noReplyConditionTime", s_ctxtPrim_7_Tag, true, TcapXApplication::Integer, 0},
{"extensionContainer", s_ctxtCstr_9_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_forwFeature[] = {
{"forwardingFeature", s_sequenceTag, true, TcapXApplication::Sequence, s_forwFeatureSeq},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_extForwInfo[] = {
{"ss-Code", s_hexTag, false, TcapXApplication::Enumerated, s_SSCode},
{"forwardingFeatureList", s_sequenceTag, false, TcapXApplication::SequenceOf, s_forwFeature},
{"extensionContainer", s_ctxtCstr_0_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_extCallBarFeatureSeq[] = {
{"basicService", s_noTag, true, TcapXApplication::Choice, s_basicServiceCode},
{"ss-Status", s_ctxtPrim_4_Tag, false, TcapXApplication::Flags, s_ssStatus},
{"extensionContainer", s_sequenceTag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_extCallBarFeature[] = {
{"ext-CallBarFeature", s_sequenceTag, true, TcapXApplication::Sequence, s_extCallBarFeatureSeq},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_extCallBarInfo[] = {
{"ss-Code", s_hexTag, false, TcapXApplication::Enumerated, s_SSCode},
{"callBarringFeatureList",s_sequenceTag, false, TcapXApplication::SequenceOf, s_extCallBarFeature},
{"extensionContainer", s_ctxtCstr_0_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_intraCUGOptions[] = {
{"noCUG-Restrictions", 0},
{"cugIC-CallBarred", 1},
{"cugOG-CallBarred", 2},
{0,0},
};
static const Parameter s_basicServiceCodeType[] = {
{"basicService", s_noTag, true, TcapXApplication::Choice, s_basicServiceCode},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_CUGSubscriptionSeq[] = {
{"cug-Index", s_intTag, false, TcapXApplication::Integer, 0},
{"cug-Interlock", s_hexTag, false, TcapXApplication::HexString, 0},
{"intraCUG-Options", s_enumTag, false, TcapXApplication::Enumerated, s_intraCUGOptions},
{"basicServiceGroupList", s_sequenceTag, true, TcapXApplication::SequenceOf, s_basicServiceCodeType},
{"extensionContainer", s_ctxtCstr_0_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_CUGSubscription[] = {
{"cug-Subscription", s_sequenceTag, false, TcapXApplication::Sequence, s_CUGSubscriptionSeq},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_interCUGRestrinctions[] = {
{"CUG-only", 0x00},
{"CUG-outgoing-access", 0x01},
{"CUG-incoming-access", 0x02},
{"CUG-both", 0x03},
{0,0},
};
static const Parameter s_CUGFeatureSeq[] = {
{"basicService", s_noTag, true, TcapXApplication::Choice, s_basicServiceCode},
{"preferentialCUG-Indicator", s_intTag, true, TcapXApplication::Integer, 0},
{"interCUG-Restrictions", s_hexTag, false, TcapXApplication::Enumerated, s_interCUGRestrinctions},
{"extensionContainer", s_sequenceTag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_CUGFeature[] = {
{"cug-Feature", s_sequenceTag, false, TcapXApplication::Sequence, s_CUGFeatureSeq},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_cugInfo[] = {
{"cug-SubscriptionList", s_sequenceTag, false, TcapXApplication::SequenceOf, s_CUGSubscription},
{"cug-FeatureList", s_sequenceTag, true, TcapXApplication::SequenceOf, s_CUGFeature},
{"extensionContainer", s_ctxtCstr_0_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_cliRestrictionOption[] = {
{"permanent", 0},
{"temporaryDefaultRestricted", 1},
{"temporaryDefaultAllowed", 2},
{0,0},
};
static const TokenDict s_overrideCategory[] = {
{"overrideEnabled", 0},
{"overrideDisabled", 1},
{0,0},
};
static const Parameter s_ssSubscriptionOption[] = {
{"cliRestrictionOption", s_ctxtPrim_2_Tag, false, TcapXApplication::Enumerated, s_cliRestrictionOption},
{"overrideCategory", s_ctxtPrim_1_Tag, false, TcapXApplication::Enumerated, s_overrideCategory},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_extSSData[] = {
{"ss-Code", s_hexTag, false, TcapXApplication::Enumerated, s_SSCode},
{"ss-Status", s_ctxtPrim_4_Tag, false, TcapXApplication::Flags, s_ssStatus},
{"ss-SubscriptionOption", s_noTag, true, TcapXApplication::Choice, s_ssSubscriptionOption},
{"basicServiceGroupList", s_sequenceTag, true, TcapXApplication::SequenceOf, s_basicServiceCodeType},
{"extensionContainer", s_ctxtCstr_5_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_EMLPPPriority[] = {
{"priorityLevel0", 0},
{"priorityLevel1", 1},
{"priorityLevel2", 2},
{"priorityLevel3", 3},
{"priorityLevel4", 4},
{"priorityLevelB", 5},
{"priorityLevelA", 6},
{0,0},
};
static const Parameter s_EMLPPInfo[] = {
{"maximumentitledPriority", s_intTag, false, TcapXApplication::Enumerated, s_EMLPPPriority},
{"defaultPriority", s_intTag, false, TcapXApplication::Enumerated, s_EMLPPPriority},
{"extensionContainer", s_sequenceTag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_extSSInfoChoice[] = {
{"forwardingInfo", s_ctxtCstr_0_Tag, false, TcapXApplication::Sequence, s_extForwInfo},
{"callBarringInfo", s_ctxtCstr_1_Tag, false, TcapXApplication::Sequence, s_extCallBarInfo},
{"cug-Info", s_ctxtCstr_2_Tag, false, TcapXApplication::Sequence, s_cugInfo},
{"ss-Data", s_ctxtCstr_3_Tag, false, TcapXApplication::Sequence, s_extSSData},
{"emlpp-Info", s_ctxtCstr_4_Tag, false, TcapXApplication::Sequence, s_EMLPPInfo},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_extSSInfo[] = {
{"SS-Info", s_noTag, false, TcapXApplication::Choice, s_extSSInfoChoice},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_odbGeneralData[] = {
{"allOG-CallsBarred", 0x01},
{"internationalOGCallsBarred", 0x02},
{"internationalOGCallsNotToHPLMN-CountryBarred", 0x04},
{"interzonalOGCallsBarred", 0x40},
{"interzonalOGCallsNotToHPLMN-CountryBarred", 0x80},
{"interzonalOGCallsAndInternationalOGCallsNotToHPLMN-CountryBarred", 0x0100},
{"premiumRateInformationOGCallsBarred", 0x08},
{"premiumRateEntertainementOGCallsBarred", 0x10},
{"ss-AccessBarred", 0x20},
{"allECT-Barred", 0x0200},
{"chargeableECT-Barred", 0x0400},
{"internationalECT-Barred", 0x0800},
{"interzonalECT-Barred", 0x1000},
{"doublyChargeableECT-Barred", 0x2000},
{"multipleECT-Barred", 0x2000},
{0,0},
};
static const TokenDict s_odbHPLMNData[] = {
{"plmn-SpecificBarringType1", 0x01},
{"plmn-SpecificBarringType2", 0x02},
{"plmn-SpecificBarringType3", 0x04},
{"plmn-SpecificBarringType4", 0x08},
{0,0},
};
static const Parameter s_odbData[] = {
{"odb-GeneralData", s_bitsTag, false, TcapXApplication::BitString, s_odbGeneralData},
{"odb-HPLMN-Data", s_bitsTag, true, TcapXApplication::BitString, s_odbHPLMNData},
{"extensionContainer", s_sequenceTag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_zoneCode[] = {
{"zoneCode", s_hexTag, false, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_voiceBroadcastData[] = {
{"groupid", s_hexTag, false, TcapXApplication::TBCD, 0},
{"broadcastInitEntitlement", s_nullTag, true, TcapXApplication::Null, 0},
{"extensionContainer", s_sequenceTag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_voiceGroupCallData[] = {
{"groupid", s_hexTag, false, TcapXApplication::TBCD, 0},
{"extensionContainer", s_sequenceTag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_OBcsmTriggerDetectionPoint[] = {
{"collectedInfo", 2},
{0,0},
};
static const TokenDict s_defaultCallHandling[] = {
{"continueCall", 0},
{"releaseCall", 1},
{0,0},
};
static const Parameter s_OBcsmCamelTDPData[] = {
{"o-BcsmTriggerDetectionPoint", s_enumTag, false, TcapXApplication::Enumerated, s_OBcsmTriggerDetectionPoint},
{"serviceKey", s_intTag, false, TcapXApplication::Integer, 0},
{"gsmSCF-Address", s_ctxtPrim_0_Tag, false, TcapXApplication::AddressString, 0},
{"defaultCallHandling", s_ctxtPrim_1_Tag, false, TcapXApplication::Enumerated, s_defaultCallHandling},
{"extensionContainer", s_ctxtCstr_2_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_camelCapabilityHandling[] = {
{"continueCall", 0},
{"releaseCall", 1},
{0,0},
};
static const Parameter s_OCSI[] = {
{"o-BcsmCamelTDPDataList", s_sequenceTag, false, TcapXApplication::SequenceOf, s_OBcsmCamelTDPData},
{"extensionContainer", s_sequenceTag, true, TcapXApplication::HexString, 0},
{"camelCapabilityHandling", s_ctxtPrim_0_Tag, true, TcapXApplication::Integer, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_ssCode[] = {
{"ss-Code", s_hexTag, false, TcapXApplication::Enumerated, s_SSCode},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_SSCamelData[] = {
{"ss-EventList", s_sequenceTag, false, TcapXApplication::SequenceOf, s_ssCode},
{"gsmSCF-Address", s_hexTag, false, TcapXApplication::AddressString, 0},
{"extensionContainer", s_ctxtCstr_0_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_SSCSI[] = {
{"ss-CamelData", s_sequenceTag, false, TcapXApplication::Sequence, s_SSCamelData},
{"extensionContainer", s_sequenceTag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_matchType[] = {
{"inhibiting", 0x00},
{"enabling", 0x01},
{0,0xff},
};
static const Parameter s_destinationNumber[] = {
{"destinationNumber", s_hexTag, false, TcapXApplication::AddressString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_destinationNumberLength[] = {
{"destinationNumberLength", s_intTag, false, TcapXApplication::Integer, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_destinationNumberCriteria[] = {
// TS 100 974 v7.15.0 page 306
{"matchType", s_ctxtPrim_0_Tag, false, TcapXApplication::Enumerated, s_matchType},
{"destinationNumberList", s_ctxtCstr_1_Tag, true, TcapXApplication::SequenceOf, s_destinationNumber},
{"destinationNumberLengthList", s_ctxtCstr_2_Tag, true, TcapXApplication::SequenceOf, s_destinationNumberLength},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_callTypeCriteria[] = {
// TS 100 974 v7.15.0 page 307
{"forwarded", 0x00},
{"notForwarded", 0x01},
{0,0xff},
};
static const Parameter s_OBcsmCamelTDPCriteria[] = {
{"o-BcsmTriggerDetectionPoint", s_enumTag, false, TcapXApplication::Enumerated, s_OBcsmTriggerDetectionPoint},
{"destinationNumberCriteria", s_ctxtCstr_0_Tag, true, TcapXApplication::Sequence, s_destinationNumberCriteria},
{"basicServiceCriteria", s_ctxtCstr_1_Tag, true, TcapXApplication::SequenceOf, s_basicServiceCodeType},
{"callTypeCriteria", s_ctxtPrim_2_Tag, true, TcapXApplication::Enumerated, s_callTypeCriteria},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_VlrCamelSubscriptionInfo[] = {
{"o-CSI", s_ctxtCstr_0_Tag, true, TcapXApplication::Sequence, s_OCSI},
{"extensionContainer", s_ctxtCstr_1_Tag, true, TcapXApplication::HexString, 0},
{"ss-CSI", s_ctxtCstr_2_Tag, true, TcapXApplication::Sequence, s_SSCSI},
{"o-BcsmCamelTDP-CriteriaList", s_ctxtCstr_4_Tag, true, TcapXApplication::SequenceOf, s_OBcsmCamelTDPCriteria},
{"tif-CSI", s_ctxtPrim_3_Tag, true, TcapXApplication::Null, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_naeaPreferredCI[] = {
// NAEAPreferredICI
{"naea-PreferredCIC", s_ctxtPrim_0_Tag, false, TcapXApplication::TBCD, 0},
{"extensionContainer", s_ctxtCstr_1_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_PDPContextSeq[] = {
{"pdp-ContextId", s_intTag, false, TcapXApplication::Integer, 0},
{"pdp-Type", s_ctxtPrim_16_Tag, false, TcapXApplication::HexString, 0},
{"pdp-Address", s_ctxtPrim_17_Tag, true, TcapXApplication::HexString, 0},
{"qos-Subscribed", s_ctxtPrim_18_Tag, false, TcapXApplication::HexString, 0},
{"vplmnAddressAllowed", s_ctxtPrim_19_Tag, true, TcapXApplication::Null, 0},
{"apn", s_ctxtPrim_20_Tag, false, TcapXApplication::HexString, 0},
{"extensionContainer", s_ctxtCstr_21_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_PDPContext[] = {
{"pdp-Context", s_sequenceTag, false, TcapXApplication::Sequence, s_PDPContextSeq},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_GPRSSubscriptionData[] = {
{"completeDataListIncluded", s_nullTag, true, TcapXApplication::Null, 0},
{"gprsDataList", s_ctxtCstr_1_Tag, false, TcapXApplication::SequenceOf, s_PDPContext},
{"extensionContainer", s_ctxtCstr_2_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_networkAccessMode[] = {
{"bothMSCAndSGSN", 0x00},
{"onlyMSC", 0x01},
{"onlySGSN", 0x02},
{0,0xff},
};
static const TokenDict s_lsaOnlyAccessIndicator[] = {
{"accessOutsideLSAsAllowed", 0x00},
{"accessOutsideLSAsRestricted", 0x01},
{0,0xff},
};
static const Parameter s_LSADataSeq[] = {
{"lsaIdentity", s_ctxtPrim_0_Tag, false, TcapXApplication::HexString, 0},
{"lsaAttributes", s_ctxtPrim_1_Tag, false, TcapXApplication::HexString, 0},
{"lsaActiveModeIndicator", s_ctxtPrim_2_Tag, true, TcapXApplication::Null, 0},
{"extensionContainer", s_ctxtCstr_3_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_LSAData[] = {
{"lsaData", s_sequenceTag, false, TcapXApplication::Sequence, s_LSADataSeq},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_LSAInformation[] = {
{"completeDataListIncluded", s_nullTag, true, TcapXApplication::Null, 0},
{"lsaOnlyAccessIndicator", s_ctxtPrim_1_Tag, true, TcapXApplication::Enumerated, s_lsaOnlyAccessIndicator},
{"lsaDataList", s_ctxtCstr_2_Tag, true, TcapXApplication::SequenceOf, s_LSAData},
{"extensionContainer", s_ctxtCstr_3_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false,TcapXApplication::None, 0},
};
static const Parameter s_GMLC[] = {
{"gmlc", s_hexTag, false, TcapXApplication::AddressString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_notificationToMSUser[] = {
{"notifyLocationAllowed", 0x00},
{"notifyAndVerify-LocationAllowedIfNoResponse", 0x01},
{"notifyAndVerify-LocationNotAllowedIfNoResponse", 0x02},
{0,0xff},
};
static const TokenDict s_GMLCRestriction[] = {
{"gmlc-List", 0x00},
{"home-Country", 0x01},
{0,0xff},
};
static const Parameter s_LCSClientExternalIDSeq[] = {
{"externalAddress", s_ctxtPrim_0_Tag, true, TcapXApplication::AddressString, 0},
{"extensionContainer", s_ctxtCstr_1_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_externalClientSeq[] = {
{"clientIdentity", s_sequenceTag, false, TcapXApplication::Sequence, s_LCSClientExternalIDSeq},
{"gmlc-Restriction", s_ctxtPrim_0_Tag, true, TcapXApplication::Enumerated, s_GMLCRestriction},
{"notificationToMSUser", s_ctxtPrim_1_Tag, true, TcapXApplication::Enumerated, s_notificationToMSUser},
{"extensionContainer", s_ctxtCstr_2_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_externalClient[] = {
{"externalClient", s_sequenceTag, false, TcapXApplication::Sequence, s_externalClientSeq},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_LCSClientInternalIDEnum[] = {
{"broadcastService", 0x00},
{"o-andM-HPLMN", 0x01},
{"o-andM-VPLMN", 0x02},
{"anonymousLocation", 0x03},
{"targetMSsubscribedService", 0x04},
{0,0xff},
};
static const Parameter s_LCSClientInternalID[] = {
{"lcsClientInternalID", s_enumTag, false, TcapXApplication::Enumerated, s_LCSClientInternalIDEnum},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_LCSPrivacyClassSeq[] = {
{"ss-Code", s_hexTag, false,TcapXApplication::Enumerated, s_SSCode},
{"ss-Status", s_hexTag, false,TcapXApplication::Flags, s_ssStatus},
{"notificationToMSUser", s_ctxtPrim_0_Tag, true, TcapXApplication::Enumerated, s_notificationToMSUser},
{"externalClientList", s_ctxtCstr_1_Tag, true, TcapXApplication::SequenceOf, s_externalClient},
{"plmnClientList", s_ctxtCstr_2_Tag, true, TcapXApplication::SequenceOf, s_LCSClientInternalID},
{"extensionContainer", s_ctxtCstr_3_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false,TcapXApplication::None, 0},
};
static const Parameter s_LCSPrivacyException[] = {
{"lcsPrivacyClass", s_sequenceTag, false, TcapXApplication::Sequence, s_LCSPrivacyClassSeq},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_MOLRClassSeq[] = {
{"ss-Code", s_hexTag, false,TcapXApplication::Enumerated, s_SSCode},
{"ss-Status", s_hexTag, false,TcapXApplication::Flags, s_ssStatus},
{"extensionContainer", s_ctxtCstr_0_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false,TcapXApplication::None, 0},
};
static const Parameter s_MOLRClass[] = {
{"mOLRClass", s_sequenceTag, false, TcapXApplication::Sequence, s_MOLRClassSeq},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_LCSInformation[] = {
{"gmlc-List", s_ctxtCstr_0_Tag, true, TcapXApplication::SequenceOf, s_GMLC},
{"lcs-PrivacyExceptionList",s_ctxtCstr_1_Tag, true, TcapXApplication::SequenceOf, s_LCSPrivacyException},
{"molr-List", s_ctxtCstr_2_Tag, true, TcapXApplication::SequenceOf, s_MOLRClass},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_contextId[] = {
// TS 100 974 v7.15.0 page 305
{"contextId", s_intTag, false, TcapXApplication::Integer, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_GPRSSubscriptionDataWithdraw[] = {
// TS 100 974 v7.15.0 page 305
{"allGPRSData", s_nullTag, false, TcapXApplication::Null, 0},
{"contextIdList", s_sequenceTag, false, TcapXApplication::SequenceOf, s_contextId},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_LSAIdentity[] = {
// TS 100 974 v7.15.0 page 300
{"lsaIdentity", s_hexTag, false, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_LSAInformationWithdraw[] = {
// TS 100 974 v7.15.0 page 305
{"allLSAData", s_nullTag, false, TcapXApplication::Null, 0},
{"lsaIdentityList", s_sequenceTag, false, TcapXApplication::SequenceOf, s_LSAIdentity},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_regionalSubscriptionResponse[] = {
// TS 100 974 v7.15.0 page 305
{"networkNode-AreaRestricted", 0},
{"tooManyZoneCodes", 1},
{"zoneCodesConflict", 2},
{"regionalSubscNotSupported", 3},
{0,0},
};
static const Parameter s_SSForBSCode[] = {
// TS 100 974 v7.15.0 page 319
{"ss-Code", s_hexTag, false, TcapXApplication::Enumerated, s_SSCode},
{"basicService", s_noTag, true, TcapXApplication::Choice, s_basicServiceCode},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_ccbsFeature[] = {
// TS 100 974 v7.15.0 page 319
{"ccbs-Index", s_ctxtPrim_0_Tag, true, TcapXApplication::Integer, 0},
{"b-subscriberNumber", s_ctxtPrim_1_Tag, true, TcapXApplication::AddressString, 0},
{"b-subscriberSubaddress", s_ctxtPrim_2_Tag, true, TcapXApplication::HexString , 0},
{"basicServiceGroup", s_ctxtPrim_3_Tag, true, TcapXApplication::Choice, s_extBasicServiceCode},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_CCBSFeature[] = {
// TS 100 974 v7.15.0 page 319
{"CCBS-Feature", s_sequenceTag, false, TcapXApplication::Sequence, s_ccbsFeature},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_genericServiceInfo[] = {
// TS 100 974 v7.15.0 page 319
{"ss-Status", s_hexTag, false, TcapXApplication::Flags, s_ssStatus},
{"cliRestrictionOption", s_enumTag, true, TcapXApplication::Enumerated, s_cliRestrictionOption},
{"maximumentitledPriority", s_intTag, true, TcapXApplication::Enumerated, s_EMLPPPriority},
{"defaultPriority", s_intTag, true, TcapXApplication::Enumerated, s_EMLPPPriority},
{"ccbs-FeatureList", s_ctxtCstr_2_Tag, true, TcapXApplication::SequenceOf, s_CCBSFeature},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_InterrogateSSRes[] = {
// TS 100 974 v7.15.0 page 319
{"ss-Status", s_ctxtPrim_0_Tag, false, TcapXApplication::Flags, s_ssStatus},
{"basicServiceGroupList", s_ctxtCstr_2_Tag, false, TcapXApplication::SequenceOf, s_basicServiceCodeType},
{"forwardingFeatureList", s_ctxtCstr_3_Tag, false, TcapXApplication::SequenceOf, s_forwFeature},
{"genericServiceInfo", s_ctxtCstr_4_Tag, false, TcapXApplication::Sequence, s_genericServiceInfo},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_guidanceInfo[] = {
{"enterPW", 0 },
{"enterNewPW", 1 },
{"enterNewPW-Again", 2 },
{0, 0},
};
static const Parameter s_hlrId[] = {
{"HLR-Id", s_hexTag, false, TcapXApplication::TBCD, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_additionalNumber[] = {
{"msc-Number", s_ctxtPrim_0_Tag, false, TcapXApplication::AddressString, 0},
{"sgsn-Number", s_ctxtPrim_1_Tag, false, TcapXApplication::AddressString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_locationInfoWithLMSI[] = {
// TS 100 974 v7.15.0 page 324
{"networkNode-Number", s_ctxtPrim_1_Tag, false, TcapXApplication::AddressString, 0},
{"lmsi", s_hexTag, true, TcapXApplication::HexString, 0},
{"extensionContainer", s_sequenceTag, true, TcapXApplication::HexString, 0},
{"gprsNodeIndicator", s_ctxtPrim_5_Tag, true, TcapXApplication::Null, 0},
{"additional-Number", s_noTag, true, TcapXApplication::Choice, s_additionalNumber},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_authenticationSetSeq[] = {
// TS 100 974 v7.15.0 page 298
{"rand", s_hexTag, false, TcapXApplication::HexString, 0},
{"sres", s_hexTag, false, TcapXApplication::HexString, 0},
{"kc", s_hexTag, false, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_authenticationSet[] = {
{"set", s_sequenceTag, false, TcapXApplication::Sequence, s_authenticationSetSeq},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_authenticationTriplet[] = {
{"triplet", s_sequenceTag, false, TcapXApplication::Sequence, s_authenticationSetSeq},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_authenticationQuintupletSeq[] = {
{"rand", s_hexTag, false, TcapXApplication::HexString, 0},
{"xres", s_hexTag, false, TcapXApplication::HexString, 0},
{"ck", s_hexTag, false, TcapXApplication::HexString, 0},
{"ik", s_hexTag, false, TcapXApplication::HexString, 0},
{"autn", s_hexTag, false, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_authenticationQuintuplet[] = {
{"quintuplet", s_sequenceTag, false, TcapXApplication::Sequence, s_authenticationQuintupletSeq},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_authChoice[] = {
{"tripletList", s_ctxtCstr_0_Tag, false, TcapXApplication::SequenceOf, s_authenticationTriplet},
{"quintupletList", s_ctxtCstr_1_Tag, false, TcapXApplication::SequenceOf, s_authenticationQuintuplet},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_epcAvSeq[] = {
{"rand", s_hexTag, false, TcapXApplication::HexString, 0},
{"xres", s_hexTag, false, TcapXApplication::HexString, 0},
{"autn", s_hexTag, false, TcapXApplication::HexString, 0},
{"kasme", s_hexTag, false, TcapXApplication::HexString, 0},
{"extensionContainer", s_sequenceTag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_EPCAV[] = {
// TS 129 002 V9.3.0 page 359
{"EPC-AV", s_sequenceTag, false, TcapXApplication::Sequence, s_epcAvSeq},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_authenticationRes[] = {
// TS 129 002 V9.3.0 page 352
{"authenticationSetList", s_noTag, true, TcapXApplication::Choice, s_authChoice},
{"extensionContainer", s_sequenceTag, true, TcapXApplication::HexString, 0},
{"eps-AuthenticationSetList", s_ctxtCstr_2_Tag, true, TcapXApplication::SequenceOf, s_EPCAV},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_alertReason[] = {
// TS 100 974 v7.15.0 page 326
{"ms-Present", 0},
{"memoryAvailable", 1},
{0,0},
};
static const Parameter s_subscriberIdentity[] = {
// TS 100 974 v7.15.0 page 335
{"imsi", s_ctxtPrim_0_Tag, false, TcapXApplication::TBCD, 0},
{"msisdn", s_ctxtPrim_1_Tag, false, TcapXApplication::AddressString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_requestedInfo[] = {
// TS 100 974 v7.15.0 page 309
{"locationInformation", s_ctxtPrim_0_Tag, true, TcapXApplication::Null, 0},
{"subscriberState", s_ctxtPrim_1_Tag, true, TcapXApplication::Null, 0},
{"extensionContainer", s_ctxtCstr_2_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_cellIdOrLAI[] = {
// TS 100 974 v7.15.0 page 335
{"cellIdFixedLength", s_ctxtPrim_0_Tag, false, TcapXApplication::CellIdFixedLength, 0},
{"laiFixedLength", s_ctxtPrim_1_Tag, false, TcapXApplication::LAIFixedLength, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_locationInformation[] = {
// TS 100 974 v7.15.0 page 309
{"ageOfLocationInformation", s_intTag, false, TcapXApplication::Integer, 0},
{"geographicalInformation", s_ctxtPrim_0_Tag, true, TcapXApplication::HexString, 0},
{"vlr-Number", s_ctxtPrim_1_Tag, true, TcapXApplication::AddressString, 0},
{"locationNumber", s_ctxtPrim_2_Tag, true, TcapXApplication::HexString, 0},
{"cellIdOrLAI", s_ctxtCstr_3_Tag, true, TcapXApplication::Choice, s_cellIdOrLAI},
{"extensionContainer", s_ctxtCstr_4_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_notReachableReason[] = {
{"msPurged", 0},
{"imsiDetached", 1},
{"restrictedArea", 2},
{"notRegistered", 3},
{0,0},
};
static const Parameter s_subscriberState[] = {
// TS 100 974 v7.15.0 page 309
{"assumedIdle", s_ctxtPrim_0_Tag, false, TcapXApplication::Null, 0},
{"camelBusy", s_ctxtPrim_1_Tag, false, TcapXApplication::Null, 0},
{"netDetNotReachable", s_enumTag, false, TcapXApplication::Enumerated, s_notReachableReason},
{"notProvidedFromVLR", s_ctxtPrim_2_Tag, false, TcapXApplication::Null, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_subscriberInfo[] = {
// TS 100 974 v7.15.0 page 309
{"locationInformation", s_ctxtCstr_0_Tag, true, TcapXApplication::Sequence, s_locationInformation},
{"subscriberState", s_ctxtCstr_1_Tag, true, TcapXApplication::Choice, s_subscriberState},
{"extensionContainer", s_ctxtCstr_2_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false,TcapXApplication::None, 0},
};
static const TokenDict s_reportingState[] = {
{"stopMonitoring", 0},
{"startMonitoring", 1},
{0,0}
};
static const TokenDict s_CCBSSubscriberStatus[] = {
{"ccbsNotIdle", 0},
{"ccbsIdle", 1},
{"ccbsNotReachable", 2},
{0,0}
};
static const Parameter s_eventReportData[] = {
// TS 100 974 v7.15.0 page 315
{"ccbs-SubscriberStatus", s_ctxtPrim_0_Tag, true, TcapXApplication::Enumerated, s_CCBSSubscriberStatus},
{"extensionContainer", s_ctxtCstr_1_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_monitoringMode[] = {
// TS 100 974 v7.15.0 page 315
{"a-side", 0},
{"b-side", 1},
{0,0}
};
static const TokenDict s_callOutcome[] = {
// TS 100 974 v7.15.0 page 316
{"success", 0},
{"failure", 1},
{"busy", 2},
{0,0}
};
static const Parameter s_callReportData[] = {
// TS 100 974 v7.15.0 page 315
{"monitoringMode", s_ctxtPrim_0_Tag, true, TcapXApplication::Enumerated, s_monitoringMode},
{"callOutcome", s_ctxtPrim_1_Tag, true, TcapXApplication::Enumerated, s_callOutcome},
{"extensionContainer", s_ctxtCstr_2_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_updateLocationArgs[] = {
// update location args
{"imsi", s_hexTag, false, TcapXApplication::TBCD, 0},
{"msc-Number", s_ctxtPrim_1_Tag, false, TcapXApplication::AddressString, 0},
{"vlr-Number", s_hexTag, false, TcapXApplication::AddressString, 0},
{"lmsi", s_ctxtPrim_10_Tag, true, TcapXApplication::HexString, 0},
{"extensionContainer",s_sequenceTag, true, TcapXApplication::HexString, 0},
{"vlr-Capability", s_ctxtCstr_6_Tag, true, TcapXApplication::Sequence, s_vlrCapability},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_updateLocationRes[] = {
{"hlr-Number", s_hexTag, false, TcapXApplication::AddressString,0},
{"extensionContainer",s_sequenceTag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_cancelLocationArgs[] = {
{"identity", s_noTag, false, TcapXApplication::Choice, s_mapIdentity},
{"cancellationType", s_enumTag, true, TcapXApplication::Enumerated, s_cancellationType},
{"extensionContainer",s_sequenceTag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_extensionContainerRes[] = {
{"extensionContainer",s_sequenceTag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_provideRoamingNumberArgs[] = {
{"imsi", s_ctxtPrim_0_Tag, false, TcapXApplication::TBCD, 0},
{"msc-Number", s_ctxtPrim_1_Tag, false, TcapXApplication::AddressString, 0},
{"msisdn", s_ctxtPrim_2_Tag, true, TcapXApplication::AddressString, 0},
{"lmsi", s_ctxtPrim_4_Tag, true, TcapXApplication::HexString, 0},
{"gsm-BearerCapability", s_ctxtCstr_5_Tag, true, TcapXApplication::Sequence, s_externalSignalInfo},
{"networkSignalInfo", s_ctxtCstr_6_Tag, true, TcapXApplication::Sequence, s_externalSignalInfo},
{"suppressionOfAnnouncement", s_ctxtPrim_7_Tag, true, TcapXApplication::Null, 0},
{"gmsc-Address", s_ctxtPrim_8_Tag, true, TcapXApplication::AddressString, 0},
{"callReferenceNumber", s_ctxtPrim_9_Tag, true, TcapXApplication::HexString, 0},
{"or-Interrogation", s_ctxtPrim_10_Tag, true, TcapXApplication::Null, 0},
{"extensionContainer", s_ctxtCstr_11_Tag, true, TcapXApplication::HexString, 0},
{"alertingPattern", s_ctxtPrim_12_Tag, true, TcapXApplication::Enumerated, s_alertPattern},
{"ccbs-Call", s_ctxtPrim_13_Tag, true, TcapXApplication::Null, 0},
{"supportedCamelPhasesInGMSC",s_ctxtPrim_15_Tag, true, TcapXApplication::BitString, s_camelPhases},
{"additionalSignalInfo", s_ctxtCstr_14_Tag, true, TcapXApplication::Sequence, s_extExtenalSignalInfo},
{"orNotSupportedInGMSC", s_ctxtPrim_16_Tag, true, TcapXApplication::Null, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_provideRoamingNumberRes[] = {
{"roamingNumber", s_hexTag, false,TcapXApplication::AddressString, 0},
{"extensionContainer", s_sequenceTag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false,TcapXApplication::None, 0},
};
static const Parameter s_insertSubscriberDataArgs[] = {
{"imsi", s_ctxtPrim_0_Tag, true, TcapXApplication::TBCD, 0},
{"msisdn", s_ctxtPrim_1_Tag, true, TcapXApplication::AddressString,0},
{"category", s_ctxtPrim_2_Tag, true, TcapXApplication::Enumerated, s_category},
{"subscriberStatus", s_ctxtPrim_3_Tag, true, TcapXApplication::Enumerated, s_subscriberStatus},
{"bearerServiceList", s_ctxtCstr_4_Tag, true, TcapXApplication::SequenceOf, s_bearerService},
{"teleserviceList", s_ctxtCstr_6_Tag, true, TcapXApplication::SequenceOf, s_teleservice},
{"provisionedSS", s_ctxtCstr_7_Tag, true, TcapXApplication::SequenceOf, s_extSSInfo},
{"odb-Data", s_ctxtCstr_8_Tag, true, TcapXApplication::Sequence, s_odbData},
{"roamingRestrictionDueToUnsupportedFeature", s_ctxtPrim_9_Tag, true, TcapXApplication::Null, 0},
{"regionalSubscriptionData", s_ctxtCstr_10_Tag, true, TcapXApplication::SequenceOf, s_zoneCode},
{"vbsSubscriptionData", s_ctxtCstr_11_Tag, true, TcapXApplication::SequenceOf, s_voiceBroadcastData},
{"vgcsSubscriptionData", s_ctxtCstr_12_Tag, true, TcapXApplication::SequenceOf, s_voiceGroupCallData},
{"vlrCamelSubscriptionInfo", s_ctxtCstr_13_Tag, true, TcapXApplication::Sequence, s_VlrCamelSubscriptionInfo},
{"extensionContainer", s_ctxtCstr_14_Tag, true, TcapXApplication::HexString, 0},
{"naea-PreferredCI", s_ctxtCstr_15_Tag, true, TcapXApplication::Sequence, s_naeaPreferredCI},
{"gprsSubscriptionData", s_ctxtCstr_16_Tag, true, TcapXApplication::Sequence, s_GPRSSubscriptionData},
{"roamingRestrictedInSgsnDueToUnsupportedFeature", s_ctxtCstr_23_Tag, true, TcapXApplication::Null, 0},
{"networkAccessMode", s_ctxtCstr_24_Tag, true, TcapXApplication::Enumerated, s_networkAccessMode},
{"lsaInformation", s_ctxtCstr_25_Tag, true, TcapXApplication::Sequence, s_LSAInformation},
{"lmu-Indicator", s_ctxtPrim_21_Tag, true, TcapXApplication::Null, 0},
{"lcsInformation", s_ctxtCstr_22_Tag, true, TcapXApplication::Sequence, s_LCSInformation},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_insertSubscriberDataRes[] = {
{"teleserviceList", s_ctxtCstr_1_Tag, true, TcapXApplication::SequenceOf, s_teleservice},
{"bearerServiceList", s_ctxtCstr_2_Tag, true, TcapXApplication::SequenceOf, s_bearerService},
{"ss-List", s_ctxtCstr_3_Tag, true, TcapXApplication::SequenceOf, s_ssCode},
{"odb-GeneralData", s_ctxtPrim_4_Tag, true, TcapXApplication::BitString, s_odbGeneralData},
{"regionalSubscriptionResponse",s_ctxtPrim_5_Tag, true, TcapXApplication::Enumerated, s_regionalSubscriptionResponse},
{"supportedCamelPhases", s_ctxtPrim_6_Tag, true, TcapXApplication::BitString, s_camelPhases},
{"extensionContainer", s_ctxtCstr_7_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_deleteSubscriberDataArgs[] = {
{"imsi", s_ctxtPrim_0_Tag, false, TcapXApplication::TBCD, 0},
{"basicServiceList", s_ctxtCstr_1_Tag, true, TcapXApplication::SequenceOf, s_basicServiceCodeType},
{"ss-List", s_ctxtCstr_2_Tag, true, TcapXApplication::SequenceOf, s_ssCode},
{"roamingRestrictionDueToUnsupportedFeature", s_ctxtPrim_4_Tag, true, TcapXApplication::Null, 0},
{"regionalSubscriptionIdentifier", s_ctxtPrim_5_Tag, true, TcapXApplication::HexString, 0},
{"vbsGroupIndication", s_ctxtPrim_7_Tag, true, TcapXApplication::Null, 0},
{"vgcsGroupIndication", s_ctxtPrim_8_Tag, true, TcapXApplication::Null, 0},
{"camelSubscriptionInfoWithdraw", s_ctxtPrim_9_Tag, true, TcapXApplication::Null, 0},
{"extensionContainer", s_ctxtCstr_6_Tag, true, TcapXApplication::HexString, 0},
{"gprsSubscriptionDataWithdraw", s_ctxtCstr_10_Tag,true, TcapXApplication::Choice, s_GPRSSubscriptionDataWithdraw},
{"roamingRestrictedInSgsnDueToUnsuppportedFeature", s_ctxtPrim_11_Tag,true, TcapXApplication::Null, 0},
{"lsaInformationWithdraw", s_ctxtCstr_12_Tag,true, TcapXApplication::Choice, s_LSAInformationWithdraw},
{"gmlc-ListWithdraw", s_ctxtPrim_13_Tag,true, TcapXApplication::Null, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_deleteSubscriberDataRes[] = {
{"regionalSubscriptionResponse", s_ctxtPrim_0_Tag, true, TcapXApplication::Enumerated, s_regionalSubscriptionResponse},
{"extensionContainer", s_sequenceTag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false,TcapXApplication::None, 0},
};
static const Parameter s_registerSSArgs[] = {
{"ss-Code", s_hexTag, false, TcapXApplication::Enumerated, s_SSCode},
{"basicService", s_noTag, true, TcapXApplication::Choice, s_basicServiceCode},
{"forwardedToNumber", s_ctxtPrim_4_Tag, true, TcapXApplication::AddressString, 0},
{"forwardedToSubaddress", s_ctxtPrim_6_Tag, true, TcapXApplication::HexString, 0},
{"noReplyConditionTime", s_ctxtPrim_5_Tag, true, TcapXApplication::Integer, 0},
{"defaultPriority", s_ctxtPrim_7_Tag, true, TcapXApplication::Enumerated, s_EMLPPPriority},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_ssInfoRes[] = {
{"ss-Info", s_noTag, false, TcapXApplication::Choice, s_extSSInfoChoice},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_ssCodeArgs[] = {
{"ss-Code", s_hexTag, false, TcapXApplication::Enumerated, s_SSCode},
{"basicService", s_noTag, true, TcapXApplication::Choice, s_basicServiceCode},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_interrogateSSRes[] = {
{"InterrogateSS-Res", s_noTag, false, TcapXApplication::Choice, s_InterrogateSSRes},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_registerPasswordArgs[] = {
{"ss-Code", s_hexTag, false, TcapXApplication::Enumerated, s_SSCode},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_registerPasswordRes[] = {
{"newPassword", s_numStrTag, false, TcapXApplication::AppString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_getPasswordArgs[] = {
{"guidanceInfo", s_enumTag, false, TcapXApplication::Enumerated, s_guidanceInfo},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_getPasswordRes[] = {
{"currentPassword", s_numStrTag, false, TcapXApplication::AppString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_updateGprsLocationArgs[] = {
{"imsi", s_hexTag, false, TcapXApplication::TBCD, 0},
{"sgsn-Number", s_hexTag, false, TcapXApplication::AddressString, 0},
{"sgsn-Address", s_hexTag, false, TcapXApplication::HexString, 0},
{"extensionContainer",s_sequenceTag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_updateGprsLocationRes[] = {
{"hlr-Number", s_hexTag, false, TcapXApplication::AddressString, 0},
{"extensionContainer",s_sequenceTag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false , TcapXApplication::None, 0},
};
static const Parameter s_sendRoutingInfoForGprsArgs[] = {
{"imsi", s_ctxtPrim_0_Tag, false, TcapXApplication::TBCD, 0},
{"ggsn-Address", s_ctxtPrim_1_Tag, true, TcapXApplication::HexString, 0},
{"ggsn-Number", s_ctxtPrim_2_Tag, false, TcapXApplication::AddressString, 0},
{"extensionContainer",s_ctxtCstr_3_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_sendRoutingInfoForGprsRes[] = {
{"sgsn-Address", s_ctxtPrim_0_Tag, false, TcapXApplication::HexString, 0},
{"ggsn-Address", s_ctxtPrim_1_Tag, true, TcapXApplication::HexString, 0},
{"mobileNotReachableReason", s_ctxtPrim_2_Tag, true, TcapXApplication::Integer, 0},
{"extensionContainer", s_ctxtCstr_3_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_failureReportArgs[] = {
{"imsi", s_ctxtPrim_0_Tag, false, TcapXApplication::TBCD, 0},
{"ggsn-Number", s_ctxtPrim_1_Tag, false, TcapXApplication::AddressString, 0},
{"ggsn-Address", s_ctxtPrim_2_Tag, true, TcapXApplication::HexString, 0},
{"extensionContainer",s_ctxtCstr_3_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_failureReportRes[] = {
{"ggsn-Address", s_ctxtPrim_0_Tag, true, TcapXApplication::HexString, 0},
{"extensionContainer",s_ctxtCstr_1_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_resetArgs[] = {
{"hlr-Number", s_hexTag, false, TcapXApplication::AddressString, 0},
{"hlr-List", s_sequenceTag, true, TcapXApplication::SequenceOf, s_hlrId},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_sendRoutingInfoForSMArgs[] = {
{"msisdn", s_ctxtPrim_0_Tag, false, TcapXApplication::AddressString, 0},
{"sm-RP-PRI", s_ctxtPrim_1_Tag, false, TcapXApplication::Bool, 0},
{"serviceCentreAddress", s_ctxtPrim_2_Tag, false, TcapXApplication::AddressString, 0},
{"extensionContainer", s_ctxtCstr_6_Tag, true, TcapXApplication::HexString, 0},
{"gprsSupportIndicator", s_ctxtPrim_7_Tag, true, TcapXApplication::Null, 0},
{"sm-RP-MTI", s_ctxtPrim_8_Tag, true, TcapXApplication::Integer, 0},
{"sm-RP-SMEA", s_ctxtPrim_9_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_sendRoutingInfoForSMRes[] = {
{"imsi", s_hexTag, false, TcapXApplication::TBCD, 0},
{"locationInfoWithLMSI", s_ctxtCstr_0_Tag, false, TcapXApplication::Sequence, s_locationInfoWithLMSI},
{"extensionContainer", s_ctxtCstr_4_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_activateTraceModeArgs[] = {
{"imsi", s_ctxtPrim_0_Tag, true, TcapXApplication::TBCD, 0},
{"traceReference", s_ctxtPrim_1_Tag, false, TcapXApplication::HexString, 0},
{"traceType", s_ctxtPrim_2_Tag, false, TcapXApplication::Integer, 0},
{"omc-Id", s_ctxtPrim_3_Tag, true, TcapXApplication::AddressString, 0},
{"extensionContainer",s_ctxtCstr_4_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_traceModeRes[] = {
{"extensionContainer",s_ctxtCstr_0_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_deactivateTraceModeArgs[] = {
{"imsi", s_ctxtPrim_0_Tag, true, TcapXApplication::TBCD, 0},
{"traceReference", s_ctxtPrim_1_Tag, false, TcapXApplication::HexString, 0},
{"extensionContainer",s_ctxtCstr_2_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_resynchronisationInfo[] = {
{"rand", s_hexTag, false, TcapXApplication::HexString, 0},
{"auts", s_hexTag, false, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_requestingNodeType[] = {
{"vlr", 0},
{"sgsn", 1},
{"s-cscf", 2},
{"bsf", 3},
{"gan-aaa-server", 4},
{"wlan-aaa-server", 5},
{"mme", 16},
{"mme-sgsn", 17},
{0, 0},
};
static const Parameter s_sendAuthenticationInfoArgs[] = {
{"imsi", s_hexTag, false, TcapXApplication::TBCD, 0},
{"numberOfRequestedVectors", s_intTag, true, TcapXApplication::Integer, 0},
{"segmentationProhibited", s_nullTag, true, TcapXApplication::Null, 0},
{"immediateResponsePreferred", s_ctxtPrim_1_Tag, true, TcapXApplication::Null, 0},
{"re-synchronisationInfo", s_sequenceTag, true, TcapXApplication::Sequence, s_resynchronisationInfo},
{"extensionContainer", s_ctxtCstr_2_Tag, true, TcapXApplication::HexString, 0},
{"requestingNodeType", s_ctxtPrim_3_Tag, true, TcapXApplication::Enumerated, s_requestingNodeType},
{"requestingPLMN-Id", s_ctxtPrim_4_Tag, true, TcapXApplication::TBCD, 0},
{"numberOfRequestedAdditional-Vectors", s_ctxtPrim_5_Tag, true, TcapXApplication::Integer, 0},
{"additionalVectorsAreForEPS", s_ctxtPrim_6_Tag, true, TcapXApplication::Null, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_sendAuthenticationInfoRes[] = {
{"sendAuthenticationInfoRes-v2", s_sequenceTag, true, TcapXApplication::SequenceOf, s_authenticationSet},
{"sendAuthenticationInfoRes-v3", s_ctxtCstr_3_Tag, true, TcapXApplication::Sequence, s_authenticationRes},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_restoreDataArgs[] = {
{"imsi", s_hexTag, false, TcapXApplication::TBCD, 0},
{"lmsi", s_hexTag, true, TcapXApplication::HexString, 0},
{"extensionContainer", s_sequenceTag, true, TcapXApplication::HexString, 0},
{"vlr-Capability", s_ctxtCstr_6_Tag, true, TcapXApplication::Sequence, s_vlrCapability},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_restoreDataRes[] = {
{"hlr-Number", s_hexTag, false, TcapXApplication::AddressString, 0},
{"msNotReachable", s_nullTag, true, TcapXApplication::Null, 0},
{"extensionContainer", s_sequenceTag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_sendIMSIArgs[] = {
{"msisdn", s_hexTag, false, TcapXApplication::AddressString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_sendIMSIRes[] = {
{"imsi", s_hexTag, false, TcapXApplication::TBCD, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_unstructuredSSArgs[] = {
{"ussd-DataCodingScheme", s_hexTag, false, TcapXApplication::HexString, 0},
{"ussd-String", s_hexTag, false, TcapXApplication::GSMString, 0},
{"alertingPattern", s_hexTag, true, TcapXApplication::Enumerated, s_alertPattern},
{"msisdn", s_ctxtPrim_0_Tag, true, TcapXApplication::AddressString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_unstructuredSSRes[] = {
{"ussd-DataCodingScheme", s_hexTag, false, TcapXApplication::HexString, 0},
{"ussd-String", s_hexTag, false, TcapXApplication::GSMString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_alertServiceCentreArgs[] = {
{"msisdn", s_hexTag, false, TcapXApplication::AddressString, 0},
{"serviceCentreAddress", s_hexTag, false, TcapXApplication::AddressString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_readyForSMArgs[] = {
{"imsi", s_ctxtPrim_0_Tag, false, TcapXApplication::TBCD, 0},
{"alertReason", s_enumTag, false, TcapXApplication::Enumerated, s_alertReason},
{"alertReasonIndicator", s_nullTag, true, TcapXApplication::Null, 0},
{"extensionContainer", s_sequenceTag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_purgeMSArgs[] = {
{"imsi", s_hexTag, false, TcapXApplication::TBCD, 0},
{"vlr-Number", s_ctxtPrim_0_Tag, true, TcapXApplication::AddressString, 0},
{"sgsn-Number", s_ctxtPrim_1_Tag, true, TcapXApplication::AddressString, 0},
{"extensionContainer",s_sequenceTag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_purgeMSRes[] = {
{"freezeTMSI", s_ctxtPrim_0_Tag, true, TcapXApplication::Null, 0},
{"freezeP-TMSI", s_ctxtPrim_1_Tag, true, TcapXApplication::Null, 0},
{"extensionContainer",s_sequenceTag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_anyTimeInterrogationArgs[] = {
{"subscriberIdentity", s_ctxtCstr_0_Tag, false, TcapXApplication::Choice, s_subscriberIdentity},
{"requestedInfo", s_ctxtCstr_1_Tag, false, TcapXApplication::Sequence, s_requestedInfo},
{"gsmSCF-Address", s_ctxtPrim_3_Tag, false, TcapXApplication::AddressString, 0},
{"extensionContainer", s_ctxtCstr_2_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_anyTimeInterrogationRes[] = {
{"subscriberInfo", s_sequenceTag, false, TcapXApplication::Sequence, s_subscriberInfo},
{"extensionContainer", s_sequenceTag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_setReportingStateArgs[] = {
{"imsi", s_ctxtPrim_0_Tag, true, TcapXApplication::TBCD, 0},
{"lmsi", s_ctxtPrim_1_Tag, true, TcapXApplication::HexString, 0},
{"ccbs-Monitoring", s_ctxtPrim_2_Tag, true, TcapXApplication::Enumerated, s_reportingState},
{"extensionContainer", s_ctxtCstr_3_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_setReportingStateRes[] = {
{"subscriberInfo", s_sequenceTag, false, TcapXApplication::Sequence, s_subscriberInfo},
{"extensionContainer", s_sequenceTag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_statusReportArgs[] = {
{"imsi", s_ctxtPrim_0_Tag, false, TcapXApplication::TBCD, 0},
{"eventReportData", s_ctxtCstr_1_Tag, true, TcapXApplication::Sequence, s_eventReportData},
{"callReportdata", s_ctxtCstr_2_Tag, true, TcapXApplication::Sequence, s_callReportData},
{"extensionContainer", s_ctxtCstr_3_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_statusReportRes[] = {
{"extensionContainer", s_ctxtCstr_0_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Operation s_mapOps[] = {
{"updateLocation", true, 2,
s_sequenceTag, s_updateLocationArgs,
s_sequenceTag, s_updateLocationRes
},
{"cancelLocation", true, 3,
s_ctxtCstr_3_Tag, s_cancelLocationArgs,
s_sequenceTag, s_extensionContainerRes
},
{"provideRoamingNumber", true, 4,
s_sequenceTag, s_provideRoamingNumberArgs,
s_sequenceTag, s_provideRoamingNumberRes
},
{"insertSubscriberData", true, 7,
s_sequenceTag, s_insertSubscriberDataArgs,
s_sequenceTag, s_insertSubscriberDataRes
},
{"deleteSubscriberData", true, 8,
s_sequenceTag, s_deleteSubscriberDataArgs,
s_sequenceTag, s_deleteSubscriberDataRes
},
{"registerSS", true, 10,
s_sequenceTag, s_registerSSArgs,
s_noTag, s_extSSInfoChoice
},
{"eraseSS", true, 11,
s_sequenceTag, s_ssCodeArgs,
s_noTag, s_extSSInfoChoice
},
{"activateSS", true, 12,
s_sequenceTag, s_ssCodeArgs,
s_noTag, s_extSSInfoChoice
},
{"deactivateSS", true, 13,
s_sequenceTag, s_ssCodeArgs,
s_noTag, s_extSSInfoChoice
},
{"interrogateSS", true, 14,
s_sequenceTag, s_ssCodeArgs,
s_noTag, s_InterrogateSSRes
},
{"registerPassword", true, 17,
s_noTag, s_registerPasswordArgs,
s_noTag, s_registerPasswordRes
},
{"getPassword", true, 18,
s_noTag, s_getPasswordArgs,
s_noTag, s_getPasswordRes
},
{"updateGprsLocation", true, 23,
s_sequenceTag, s_updateGprsLocationArgs,
s_sequenceTag, s_updateGprsLocationRes
},
{"sendRoutingInfoForGprs", true, 24,
s_sequenceTag, s_sendRoutingInfoForGprsArgs,
s_sequenceTag, s_sendRoutingInfoForGprsRes
},
{"failureReport", true, 25,
s_sequenceTag, s_failureReportArgs,
s_sequenceTag, s_failureReportRes
},
{"reset", true, 37,
s_sequenceTag, s_resetArgs,
s_noTag, 0
},
{"forwardCheckSS-Indication", true, 38,
s_noTag, 0,
s_noTag, 0
},
{"sendRoutingInfoForSM", true, 45,
s_sequenceTag, s_sendRoutingInfoForSMArgs,
s_sequenceTag, s_sendRoutingInfoForSMRes
},
{"activateTraceMode", true, 50,
s_sequenceTag, s_activateTraceModeArgs,
s_sequenceTag, s_traceModeRes
},
{"deactivateTraceMode", true, 51,
s_sequenceTag, s_deactivateTraceModeArgs,
s_sequenceTag, s_traceModeRes
},
{"sendAuthenticationInfo", true, 56,
s_noTag, s_sendAuthenticationInfoArgs,
s_noTag, s_sendAuthenticationInfoRes
},
{"restoreData", true, 57,
s_sequenceTag, s_restoreDataArgs,
s_sequenceTag, s_restoreDataRes
},
{"sendIMSI", true, 58,
s_noTag, s_sendIMSIArgs,
s_noTag, s_sendIMSIRes
},
{"processUnstructuredSS-Request", true, 59,
s_sequenceTag, s_unstructuredSSArgs,
s_sequenceTag, s_unstructuredSSRes
},
{"unstructuredSS-Request", true, 60,
s_sequenceTag, s_unstructuredSSArgs,
s_sequenceTag, s_unstructuredSSRes
},
{"unstructuredSS-Notify", true, 61,
s_sequenceTag, s_unstructuredSSArgs,
s_noTag, 0
},
{"alertServiceCentre", true, 64,
s_sequenceTag, s_alertServiceCentreArgs,
s_noTag, 0
},
{"readyForSM", true, 66,
s_sequenceTag, s_readyForSMArgs,
s_sequenceTag, s_extensionContainerRes
},
{"purgeMS", true, 67,
s_ctxtCstr_3_Tag, s_purgeMSArgs,
s_sequenceTag, s_purgeMSRes
},
{"anyTimeInterrogation", true, 71,
s_sequenceTag, s_anyTimeInterrogationArgs,
s_sequenceTag, s_anyTimeInterrogationRes
},
{"setReportingState", true, 73,
s_sequenceTag, s_setReportingStateArgs,
s_sequenceTag, s_setReportingStateRes
},
{"statusReport", true, 74,
s_sequenceTag, s_statusReportArgs,
s_sequenceTag, s_statusReportRes
},
{"", false, 0,
s_noTag, 0,
s_noTag, 0
},
};
static const Capability s_camelCapab[] = {
{"Camel", {"initialDP", "assistRequestInstructions", "establishTemporaryConnection", "disconnectForwardConnection",
"connectToResource", "connect", "releaseCall", "requestReportBCSMEvent","eventReportBCSM", "continue", "resetTimer",
"furnishChargingInformation", "applyCharging", "applyChargingReport", "callInformationReport", "callInformationRequest",
"sendChargingInformation", "playAnnouncement", "promptAndCollectUserInformation", "specializedResourceReport",
"cancel", "activityTest", ""}},
{0, {""}},
};
static TokenDict s_eventTypeBCSM[] = {
{"collectedInfo", 2},
{"routeSelectFailure", 4},
{"oCalledPartyBusy", 5},
{"oNoAnswer", 6},
{"oAnswer", 7},
{"oDisconnect", 9},
{"oAbandon", 10},
{"termAttemptAuthorized", 12},
{"tBusy", 13},
{"tNoAnswer", 14},
{"tAnswer", 15},
{"tDisconnect", 17},
{"tAbandon", 18},
{"", 0}
};
static TokenDict s_naCICSelectionType[] = {
{"not-indicated", 0x00},
{"subscribed-not-dialed", 0x01},
{"subscribed-and-dialed", 0x02},
{"subscribed-dialing-undeterminded", 0x03},
{"dialed-CIC-not-subscribed", 0x04},
{"", 0}
};
static const Parameter s_naCarrierInformationSeq[] = {
{"naCarrierId", s_ctxtPrim_0_Tag, true, TcapXApplication::TBCD, 0}, //Carrier digits
{"naCICSelectionType", s_ctxtPrim_1_Tag, true, TcapXApplication::Enumerated, s_naCICSelectionType},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_initialDPArgExtension[] = {
{"naCarrierInformation", s_ctxtCstr_0_Tag, true, TcapXApplication::Sequence, s_naCarrierInformationSeq},
{"gmscAddress", s_ctxtPrim_1_Tag, true, TcapXApplication::AddressString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static Parameter s_bearerCap[] = {
{"bearerCap", s_ctxtPrim_0_Tag, false, TcapXApplication::UserServiceInfo, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_initialDPArgs[] = {
{"serviceKey", s_ctxtPrim_0_Tag, false, TcapXApplication::Integer, 0},
{"calledPartyNumber", s_ctxtPrim_2_Tag, true, TcapXApplication::CalledPartyNumber, 0},
{"callingPartyNumber", s_ctxtPrim_3_Tag, true, TcapXApplication::CallingPartyNumber, 0},
{"callingPartysCategory", s_ctxtPrim_5_Tag, true, TcapXApplication::Enumerated, s_category},
// TODO decode iPSSPCapabilities according to ETSI TS 101 046 V7.1.0 (2000-07) page 42
{"iPSSPCapabilities", s_ctxtPrim_8_Tag, true, TcapXApplication::HexString, 0}, // might need further decoding
{"locationNumber", s_ctxtPrim_10_Tag, true, TcapXApplication::LocationNumber, 0},
{"originalCalledPartyID", s_ctxtPrim_12_Tag, true, TcapXApplication::OriginalCalledNumber, 0},
{"extensions", s_ctxtCstr_15_Tag, true, TcapXApplication::HexString, 0},
{"highLayerCompatibility", s_ctxtPrim_23_Tag, true, TcapXApplication::HiLayerCompat, 0}, // might need further decoding
{"additionalCallingPartyNumber", s_ctxtPrim_25_Tag, true, TcapXApplication::TBCD, 0}, // not sure about this either
{"bearerCapability", s_ctxtPrim_27_Tag, true, TcapXApplication::Choice, s_bearerCap},
{"eventTypeBCSM", s_ctxtPrim_28_Tag, true, TcapXApplication::Enumerated, s_eventTypeBCSM},
{"redirectingPartyID", s_ctxtPrim_29_Tag, true, TcapXApplication::RedirectingNumber, 0},
{"redirectionInformation", s_ctxtPrim_30_Tag, true, TcapXApplication::RedirectionInformation, 0},
{"imsi", s_ctxtPrim_50_Tag, true, TcapXApplication::TBCD, 0},
{"subscriberState", s_ctxtPrim_51_Tag, true, TcapXApplication::Choice, s_subscriberState},
{"locationInformation", s_ctxtPrim_52_Tag, true, TcapXApplication::Sequence, s_locationInformation},
{"ext-basicServiceCode", s_ctxtPrim_53_Tag, true, TcapXApplication::Choice, s_basicServiceCode},
{"callReferenceNumber", s_ctxtPrim_54_Tag, true, TcapXApplication::HexString, 0},
{"mscAddress", s_ctxtPrim_55_Tag, true, TcapXApplication::AddressString, 0},
{"calledPartyBCDNumber", s_ctxtPrim_56_Tag, true, TcapXApplication::AddressString, 0}, //should be checked
{"timeAndTimezone", s_ctxtPrim_57_Tag, true, TcapXApplication::TBCD, 0},//might need special decoding
{"gsm-ForwardingPending", s_ctxtPrim_58_Tag, true, TcapXApplication::Null, 0},
{"initialDPArgExtension", s_ctxtCstr_59_Tag, true, TcapXApplication::Sequence, s_initialDPArgExtension},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_monitorMode[] = {
{"interrupted", 0x00},
{"notifyAndContinue", 0x01},
{"transparent", 0x02},
{"", 0},
};
static const TokenDict s_legType[] = {
{"leg1", 0x01},
{"leg2", 0x02},
{"", 0},
};
static const Parameter s_legID[] = {
{"sendingSideID", s_ctxtPrim_0_Tag, false, TcapXApplication::Enumerated, s_legType},
{"receivingSideID", s_ctxtPrim_1_Tag, false, TcapXApplication::Enumerated, s_legType},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_DPSpecificCriteria[] = {
{"applicationTimer",s_ctxtPrim_1_Tag, false, TcapXApplication::Integer, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_bcsmEventSeq[] = {
{"eventTypeBCSM", s_ctxtPrim_0_Tag, false, TcapXApplication::Enumerated, s_eventTypeBCSM},
{"monitorMode", s_ctxtPrim_1_Tag, false, TcapXApplication::Enumerated, s_monitorMode},
{"legID", s_ctxtPrim_2_Tag, true, TcapXApplication::Choice, s_legID},
{"dPSpecificCriteria", s_ctxtPrim_30_Tag,true, TcapXApplication::Choice, s_DPSpecificCriteria},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_bcsmEvent[] = {
{"bcsmEvent", s_sequenceTag, false, TcapXApplication::Sequence, s_bcsmEventSeq},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_requestReportBCSMEventArgs[] = {
{"bcsmEvents", s_ctxtCstr_0_Tag, false, TcapXApplication::SequenceOf, s_bcsmEvent},
{"extensions", s_ctxtCstr_2_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_receivingSideID[] = {
{"receivingSideID", s_ctxtPrim_1_Tag, false, TcapXApplication::Enumerated, s_legType},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_failureCause[] = {
// failureCause := Cause (should find encoding, for now treated as hex string)
{"failureCause", s_ctxtPrim_0_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_busyCause[] = {
// busyCause := Cause (should find encoding, for now treated as hex string)
{"busyCause", s_ctxtPrim_0_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_releaseCause[] = {
// releaseCause := Cause (should find encoding, for now treated as hex string)
{"releaseCause", s_ctxtPrim_0_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_tNoAsnwerInfo[] = {
{"callForwarded", s_ctxtPrim_50_Tag, true, TcapXApplication::Null, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_tBusyInfo[] = {
// busyCause := Cause (should find encoding, for now treated as hex string)
{"busyCause", s_ctxtPrim_0_Tag, true, TcapXApplication::HexString, 0},
{"callForwarded", s_ctxtPrim_50_Tag, true, TcapXApplication::Null, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_eventSpecificInformationBCSM[] = {
{"routeSelectFailureSpecificInfo", s_ctxtCstr_2_Tag, false, TcapXApplication::Sequence, s_failureCause},
{"oCalledPartyBusySpecificInfo", s_ctxtCstr_3_Tag, false, TcapXApplication::Sequence, s_busyCause},
{"oNoAnswerSpecificInfo", s_ctxtCstr_4_Tag, false, TcapXApplication::Sequence, 0},
{"oAnswerSpecificInfo", s_ctxtCstr_5_Tag, false, TcapXApplication::Sequence, 0},
{"oDisconnectSpecificInfo", s_ctxtCstr_7_Tag, false, TcapXApplication::Sequence, s_releaseCause},
{"tBusySpecificInfo", s_ctxtCstr_8_Tag, false, TcapXApplication::Sequence, s_tBusyInfo},
{"tNoAnswerSpecificInfo", s_ctxtCstr_9_Tag, false, TcapXApplication::Sequence, s_tNoAsnwerInfo},
{"tAnswerSpecificInfo", s_ctxtCstr_10_Tag, false, TcapXApplication::Sequence, 0},
{"tDisconnectSpecificInfo", s_ctxtCstr_12_Tag, false, TcapXApplication::Sequence, s_releaseCause},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_messageType[] = {
{"request", 0x00},
{"notification", 0x01},
{"", 0},
};
static const Parameter s_miscCallInfoSeq[] = {
{"messageType", s_ctxtPrim_0_Tag, false, TcapXApplication::Enumerated, s_messageType},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_eventReportBCSMArgs[] = {
{"eventTypeBCSM", s_ctxtPrim_0_Tag, false, TcapXApplication::Enumerated, s_eventTypeBCSM},
{"eventSpecificInformationBCSM", s_ctxtPrim_2_Tag, true, TcapXApplication::Choice, s_eventSpecificInformationBCSM},
{"legID", s_ctxtPrim_3_Tag, true, TcapXApplication::Choice, s_receivingSideID},
{"miscCallInfo", s_ctxtCstr_4_Tag, false, TcapXApplication::Sequence, s_miscCallInfoSeq},
{"extensions", s_ctxtCstr_5_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_calledPartyNumber[] = {
{"calledPartyNumber", s_hexTag, false, TcapXApplication::CalledPartyNumber, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_genericNumber[] = {
{"genericNumber", s_hexTag, false, TcapXApplication::GenericNumber, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_naInfoSeq[] = {
{"naCarrierInformation", s_ctxtCstr_0_Tag, true, TcapXApplication::Sequence, s_naCarrierInformationSeq},
// NA Oli information takes the same value as defined in ANSI ISUP T1.113
{"naOliInfo", s_ctxtPrim_1_Tag, true, TcapXApplication::HexString, 0},
{"naChargeNumber", s_ctxtPrim_2_Tag, true, TcapXApplication::ChargeNumber, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_connectArgs[] = {
{"destinationRoutingAddress", s_ctxtCstr_0_Tag, false, TcapXApplication::SequenceOf, s_calledPartyNumber},
//alertingPattern decoded as hex string, encoding in GSM 09.02 (ref. 14)
{"alertingPattern", s_ctxtPrim_1_Tag, true, TcapXApplication::HexString, 0},
{"originalCalledPartyID", s_ctxtPrim_6_Tag, true, TcapXApplication::OriginalCalledNumber, 0},
{"extensions", s_ctxtCstr_10_Tag, true, TcapXApplication::HexString, 0},
{"callingPartysCategory", s_ctxtPrim_28_Tag, true, TcapXApplication::Enumerated, s_category},
{"redirectingPartyID", s_ctxtPrim_29_Tag, true, TcapXApplication::RedirectingNumber, 0},
{"redirectionInformation", s_ctxtPrim_30_Tag, true, TcapXApplication::RedirectionInformation, 0},
{"genericNumbers", s_ctxtCstr_14_Tag, true, TcapXApplication::SetOf, s_genericNumber},
{"suppressionOfAnnouncement", s_ctxtPrim_55_Tag, true, TcapXApplication::Null, 0},
{"oCSIApplicable", s_ctxtPrim_56_Tag, true, TcapXApplication::Null, 0},
{"na-Info", s_ctxtCstr_57_Tag, true, TcapXApplication::Sequence, s_naInfoSeq},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_releaseCallArgs[] = {
// TODO - decode Cause (ETS 300 356-1 [3] Cause and Location values refer to Q.850).
{"cause", s_hexTag, false, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_assistRequestInstructionsArgs[] = {
// Defined as Digits - see for encoding ETS 300 356-1 [3] Generic Number
{"correlationID", s_ctxtPrim_0_Tag, false, TcapXApplication::TBCD, 0},
// ETSI TS 101 046 - GSM CAP specification (CAMEL) page 42 for further decoding
{"iPSSPCapabilities", s_ctxtPrim_2_Tag, false, TcapXApplication::HexString, 0},
{"extensions", s_ctxtCstr_3_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_bothwayThroughConnectionInd[] = {
{"bothwayPathRequired", 0x00},
{"bothwayPathNotRequired", 0x01},
{"", 0},
};
static const Parameter s_serviceInteractionIndicatorsTwo[] = {
// FROM CS2-datatypes { ccitt(0) identified-organization(4) etsi(0) inDomain(1)
// in-network(1) CS2(20) modules(0) in-cs2-datatypes (0) version1(0)}
{"bothwayThroughConnectionInd", s_ctxtPrim_2_Tag, true, TcapXApplication::Enumerated, s_bothwayThroughConnectionInd},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_establishTemporaryConnectionArgs[] = {
//Digits - see for encoding ETS 300 356-1 [3] , definde ETSI TS 101 046 - GSM CAP specification (CAMEL) page 42
{"assistingSSPIPRoutingAddress", s_ctxtPrim_0_Tag, false, TcapXApplication::TBCD, 0},
// Defined as Digits - see for encoding ETS 300 356-1 [3] Generic Number
{"correlationID", s_ctxtPrim_1_Tag, true, TcapXApplication::TBCD, 0},
{"scfID", s_ctxtPrim_3_Tag, true, TcapXApplication::HexString, 0},
{"extensions", s_ctxtCstr_4_Tag, true, TcapXApplication::HexString, 0},
{"serviceInteractionIndicatorsTwo",s_ctxtCstr_7_Tag, true, TcapXApplication::Sequence, s_serviceInteractionIndicatorsTwo},
{"na-Info", s_ctxtCstr_50_Tag,true, TcapXApplication::Sequence, s_naInfoSeq},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_resourceAddress[] = {
{"ipRoutingAddress", s_ctxtPrim_0_Tag, false, TcapXApplication::CalledPartyNumber, 0},
{"none", s_ctxtPrim_3_Tag, false, TcapXApplication::Null, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_connectToResourceArgs[] = {
{"resourceAddress", s_noTag, false, TcapXApplication::Choice, s_resourceAddress},
{"extensions", s_ctxtCstr_4_Tag, true, TcapXApplication::HexString, 0},
{"serviceInteractionIndicatorsTwo",s_ctxtCstr_7_Tag, true, TcapXApplication::Sequence, s_serviceInteractionIndicatorsTwo},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_timerID[] = {
{"tssf", 0x00},
{"", 0x01},
};
static const Parameter s_resetTimerArgs[] = {
{"timerID", s_ctxtPrim_0_Tag, false, TcapXApplication::Enumerated, s_timerID},
{"timervalue", s_ctxtPrim_1_Tag, false, TcapXApplication::Integer, 0},
{"extensions", s_ctxtCstr_2_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_sendingSideID[] = {
{"sendingSideID", s_ctxtPrim_0_Tag, false, TcapXApplication::Enumerated, s_legType},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_fCIBCCCAMELsequenceSeq[] = {
{"freeFormatData", s_ctxtPrim_0_Tag, false, TcapXApplication::HexString, 0},
{"partyToCharge", s_ctxtPrim_1_Tag, false, TcapXApplication::Choice, s_sendingSideID},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_fCIBillingChargingCharacteristicsChoice[] = {
{"fCIBCCCAMELsequence1", s_ctxtPrim_0_Tag, false, TcapXApplication::Sequence, s_fCIBCCCAMELsequenceSeq},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_FCIBillingChargingCharacteristics[] = {
{"fCIBillingChargingCharacteristics", s_hexTag, false, TcapXApplication::Choice, s_fCIBillingChargingCharacteristicsChoice},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_releaseIfdurationExceeded[] = {
{"tone", s_ctxtPrim_1_Tag, false, TcapXApplication::Bool, 0},
{"extensions", s_ctxtCstr_10_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_timeDuratinChargingSeq[] = {
{"maxCallPeriodDuration", s_ctxtPrim_0_Tag, false, TcapXApplication::Integer, 0},
{"releaseIfdurationExceeded", s_ctxtCstr_1_Tag, true, TcapXApplication::Sequence, s_releaseIfdurationExceeded},
{"tariffSwitchInterval", s_ctxtPrim_2_Tag, true, TcapXApplication::Integer, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_aChBillingChargingCharacteristics[] = {
{"timeDurationCharging", s_ctxtCstr_0_Tag, false, TcapXApplication::Sequence, s_timeDuratinChargingSeq},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_applyChargingArgs[] = {
{"aChBillingChargingCharacteristics", s_ctxtPrim_0_Tag, false, TcapXApplication::Choice, s_aChBillingChargingCharacteristics},
{"partyToCharge", s_ctxtPrim_2_Tag, false, TcapXApplication::Choice, s_sendingSideID},
{"extensions", s_ctxtCstr_3_Tag, true, TcapXApplication::HexString,0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_timeIfTariffSwitchSeq[] = {
{"timeSinceTariffSwitch", s_ctxtPrim_0_Tag, false, TcapXApplication::Integer, 0},
{"tariffSwitchInterval", s_ctxtPrim_1_Tag, true, TcapXApplication::Integer, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_timeInformation[] = {
{"timeIfNoTariffSwitch", s_ctxtPrim_0_Tag, false, TcapXApplication::Integer, 0},
{"timeIfTariffSwitch", s_ctxtCstr_1_Tag, false, TcapXApplication::Sequence, s_timeIfTariffSwitchSeq},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_timeDurationChargingResSeq[] = {
{"partyToCharge", s_ctxtPrim_0_Tag, false, TcapXApplication::Choice, s_receivingSideID},
{"timeInformation", s_ctxtPrim_1_Tag, false, TcapXApplication::Choice, s_timeInformation},
{"callActive", s_ctxtPrim_2_Tag, false, TcapXApplication::Bool, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_callResultChoice[] = {
{"timeDurationChargingResult", s_ctxtCstr_0_Tag, false, TcapXApplication::Sequence, s_timeDurationChargingResSeq},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_callResult[] = {
{"callResult", s_hexTag, false, TcapXApplication::Choice, s_callResultChoice},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_requestedInformationType[] = {
{"callAttemptElapsedTime", 0x00},
{"callStopTime", 0x01},
{"callConnectedElapsedTime", 0x02},
{"releaseCause", 0x1e},
{"", 0xff},
};
static const Parameter s_requestedInformationValue[] = {
{"callAttemptElapsedTimeValue", s_ctxtPrim_0_Tag, false, TcapXApplication::Integer, 0},
{"callStopTimeValue", s_ctxtPrim_1_Tag, false, TcapXApplication::TBCD, 0},
{"callConnectedElapsedTimeValue",s_ctxtPrim_2_Tag, false, TcapXApplication::Integer, 0},
{"releaseCauseValue", s_ctxtPrim_30_Tag,false, TcapXApplication::HexString,0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_requestedInformationSeq[] = {
{"requestedInformationType", s_ctxtPrim_0_Tag, false, TcapXApplication::Enumerated, s_requestedInformationType},
{"requestedInformationValue", s_ctxtPrim_1_Tag, false, TcapXApplication::Choice, s_requestedInformationValue},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_requestedInformation[] = {
{"requestedInformation", s_sequenceTag, false, TcapXApplication::Sequence, s_requestedInformationSeq},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_callInformationArgs[] = {
{"requestedInformationList", s_ctxtCstr_0_Tag, false,TcapXApplication::SequenceOf, s_requestedInformation},
{"extensions", s_ctxtCstr_2_Tag, true, TcapXApplication::HexString, 0},
{"legID", s_ctxtPrim_3_Tag, true, TcapXApplication::Choice, s_receivingSideID},
{"", s_noTag, false,TcapXApplication::None, 0},
};
static const Parameter s_requestedInfoType[] = {
{"requestedInformationType", s_enumTag, false, TcapXApplication::Enumerated, s_requestedInformationType},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_callInformationRequestArgs[] = {
{"requestedInformationTypeList", s_ctxtCstr_0_Tag, false,TcapXApplication::SequenceOf, s_requestedInfoType},
{"extensions", s_ctxtCstr_2_Tag, true, TcapXApplication::HexString, 0},
{"legID", s_ctxtPrim_3_Tag, true, TcapXApplication::Choice, s_sendingSideID},
{"", s_noTag, false,TcapXApplication::None, 0},
};
static const Parameter s_CAIGSM0224Seq[] = {
{"e1", s_ctxtPrim_0_Tag, true, TcapXApplication::Integer, 0},
{"e2", s_ctxtPrim_1_Tag, true, TcapXApplication::Integer, 0},
{"e3", s_ctxtPrim_2_Tag, true, TcapXApplication::Integer, 0},
{"e4", s_ctxtPrim_3_Tag, true, TcapXApplication::Integer, 0},
{"e5", s_ctxtPrim_4_Tag, true, TcapXApplication::Integer, 0},
{"e6", s_ctxtPrim_5_Tag, true, TcapXApplication::Integer, 0},
{"e7", s_ctxtPrim_6_Tag, true, TcapXApplication::Integer, 0},
{"", s_noTag, false,TcapXApplication::None, 0},
};
static const Parameter s_AOCSubsequentSeq[] = {
{"cAI-GSM0224", s_ctxtCstr_0_Tag, false,TcapXApplication::Sequence, s_CAIGSM0224Seq},
{"tariffSwitchInterval", s_ctxtPrim_1_Tag, true, TcapXApplication::Integer, 0},
{"", s_noTag, false,TcapXApplication::None, 0},
};
static const Parameter s_AOCBeforeAnswerSeq[] = {
{"aOCInitial", s_ctxtCstr_0_Tag, false,TcapXApplication::Sequence, s_CAIGSM0224Seq},
{"aOCSubsequent", s_ctxtCstr_1_Tag, true, TcapXApplication::Sequence, s_AOCSubsequentSeq},
{"", s_noTag, false,TcapXApplication::None, 0},
};
static const Parameter s_sCIBillingChargingCharacteristics[] = {
{"aOCBeforeAnswer", s_ctxtCstr_0_Tag, false, TcapXApplication::Sequence, s_AOCBeforeAnswerSeq},
{"aOCAfterAnswer", s_ctxtCstr_1_Tag, true, TcapXApplication::Sequence, s_AOCSubsequentSeq},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_sendChargingInformationArgs[] = {
{"sCIBillingChargingCharacteristics", s_ctxtPrim_0_Tag, false, TcapXApplication::Choice, s_sCIBillingChargingCharacteristics},
{"partyToCharge", s_ctxtPrim_1_Tag, false, TcapXApplication::Choice, s_sendingSideID},
{"extensions", s_ctxtCstr_2_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_textSeq[] = {
{"messageContent", s_ctxtPrim_0_Tag, false, TcapXApplication::AppString, 0},
{"attributes", s_ctxtPrim_1_Tag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_elementaryMessageID[] = {
{"elementaryMessageID", s_intTag, false, TcapXApplication::Integer, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_variablePartChoice[] = {
{"integer", s_ctxtPrim_0_Tag, false, TcapXApplication::Integer, 0},
{"number", s_ctxtPrim_1_Tag, false, TcapXApplication::TBCD, 0},
{"time", s_ctxtPrim_2_Tag, false, TcapXApplication::TBCD, 0},
{"date", s_ctxtPrim_3_Tag, false, TcapXApplication::TBCD, 0},
{"price", s_ctxtPrim_4_Tag, false, TcapXApplication::TBCD, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_variablePart[] = {
{"variablePart", s_noTag, false, TcapXApplication::Choice, s_variablePartChoice},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_variableMessageSeq[] = {
{"elementaryMessageID", s_ctxtPrim_0_Tag, false, TcapXApplication::Integer, 0},
{"variableParts", s_ctxtCstr_1_Tag, false, TcapXApplication::SequenceOf, s_variablePart},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_messageID[] = {
{"elementaryMessageID", s_ctxtPrim_0_Tag, false, TcapXApplication::Integer, 0},
{"text", s_ctxtCstr_1_Tag, false, TcapXApplication::Sequence, s_textSeq},
{"elementaryMessageIDs",s_ctxtCstr_29_Tag,false, TcapXApplication::SequenceOf, s_elementaryMessageID},
{"variableMessage", s_ctxtCstr_30_Tag,false, TcapXApplication::Sequence, s_variableMessageSeq},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_inbandInfoSeq[] = {
{"messageID", s_ctxtPrim_0_Tag, false,TcapXApplication::Choice, s_messageID},
{"numberOfRepetitions", s_ctxtPrim_1_Tag, true, TcapXApplication::Integer, 0},
{"duration", s_ctxtPrim_2_Tag, true, TcapXApplication::Integer, 0},
{"interval", s_ctxtPrim_3_Tag, true, TcapXApplication::Integer, 0},
{"", s_noTag, false,TcapXApplication::None, 0},
};
static const Parameter s_toneSeq[] = {
{"toneID", s_ctxtPrim_0_Tag, false, TcapXApplication::Integer, 0},
{"duration", s_ctxtPrim_1_Tag, true, TcapXApplication::Integer, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_informationToSend[] = {
{"inbandInfo", s_ctxtCstr_0_Tag, false, TcapXApplication::Sequence, s_inbandInfoSeq},
{"tone", s_ctxtCstr_1_Tag, false, TcapXApplication::Sequence, s_toneSeq},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_playAnnouncementArgs[] = {
{"informationToSend", s_ctxtPrim_0_Tag, false, TcapXApplication::Choice, s_informationToSend},
{"disconnectFromIPForbidden", s_ctxtPrim_1_Tag, false, TcapXApplication::Bool, 0},
{"requestAnnouncementComplete", s_ctxtPrim_2_Tag, false, TcapXApplication::Bool, 0},
{"extensions", s_ctxtCstr_3_Tag, true, TcapXApplication::HexString,0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_errorTreatment[] = {
{"stdErrorAndInfo", 0x00},
{"help", 0x01},
{"repeatPrompt", 0x02},
{"", 0xff},
};
static const Parameter s_collectedInfoSeq[] = {
{"minimumNbOfDigits", s_ctxtPrim_0_Tag, false, TcapXApplication::Integer, 0},
{"maximumNbOfDigits", s_ctxtPrim_1_Tag, false, TcapXApplication::Integer, 0},
{"endOfReplyDigit", s_ctxtPrim_2_Tag, true, TcapXApplication::HexString, 0},
{"cancelDigit", s_ctxtPrim_3_Tag, true, TcapXApplication::HexString, 0},
{"startDigit", s_ctxtPrim_4_Tag, true, TcapXApplication::HexString, 0},
{"firstDigitTimeOut", s_ctxtPrim_5_Tag, false, TcapXApplication::Integer, 0},
{"interDigitTimeOut", s_ctxtPrim_6_Tag, false, TcapXApplication::Integer, 0},
{"errorTreatment", s_ctxtPrim_7_Tag, false, TcapXApplication::Enumerated,s_errorTreatment},
{"interruptableAnnInd", s_ctxtPrim_8_Tag, false, TcapXApplication::Bool, 0},
{"voiceInformation", s_ctxtPrim_9_Tag, false, TcapXApplication::Bool, 0},
{"voiceBack", s_ctxtPrim_10_Tag, false, TcapXApplication::Bool, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_collectedInfo[] = {
{"collectedDigits", s_ctxtCstr_0_Tag, false, TcapXApplication::Sequence, s_collectedInfoSeq},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_promptAndCollectUserInformationArgs[] = {
{"collectedInfo", s_ctxtPrim_0_Tag, false, TcapXApplication::Choice, s_collectedInfo},
{"disconnectFromIPForbidden", s_ctxtPrim_1_Tag, false, TcapXApplication::Bool, 0},
{"informationToSend", s_ctxtPrim_2_Tag, true, TcapXApplication::Choice, s_informationToSend},
{"extensions", s_ctxtCstr_3_Tag, true, TcapXApplication::HexString,0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_specializedResourceReportArgs[] = {
{"specializedResourceReportArgs", s_nullTag, false, TcapXApplication::Null, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_cancelChoice[] = {
{"invokeID", s_ctxtPrim_0_Tag, false, TcapXApplication::Integer, 0},
{"allRequests", s_ctxtPrim_1_Tag, false, TcapXApplication::Null, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_cancelArgs[] = {
{"cancelArg", s_noTag, false, TcapXApplication::Choice, s_cancelChoice},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Operation s_camelOps[] = {
{"initialDP", true, 0,
s_sequenceTag, s_initialDPArgs,
s_noTag, 0
},
{"assistRequestInstructions", true, 16,
s_sequenceTag, s_assistRequestInstructionsArgs,
s_noTag, 0
},
{"establishTemporaryConnection", true, 17,
s_sequenceTag, s_establishTemporaryConnectionArgs,
s_noTag, 0
},
{"disconnectForwardConnection", true, 18,
s_noTag, 0,
s_noTag, 0
},
{"connectToResource", true, 19,
s_sequenceTag, s_connectToResourceArgs,
s_noTag, 0
},
{"connect", true, 20,
s_sequenceTag, s_connectArgs,
s_noTag, 0
},
{"releaseCall", true, 22,
s_noTag, s_releaseCallArgs,
s_noTag, 0
},
{"requestReportBCSMEvent", true, 23,
s_sequenceTag, s_requestReportBCSMEventArgs,
s_noTag, 0
},
{"eventReportBCSM", true, 24,
s_sequenceTag, s_eventReportBCSMArgs,
s_noTag, 0
},
{"continue", true, 31,
s_noTag, 0,
s_noTag, 0
},
{"resetTimer", true, 33,
s_sequenceTag, s_resetTimerArgs,
s_noTag, 0
},
{"furnishChargingInformation", true, 34,
s_noTag, s_FCIBillingChargingCharacteristics,
s_noTag, 0
},
{"applyCharging", true, 35,
s_sequenceTag, s_applyChargingArgs,
s_noTag, 0
},
{"applyChargingReport", true, 36,
s_noTag, s_callResult,
s_noTag, 0
},
{"callInformationReport", true, 44,
s_sequenceTag, s_callInformationArgs,
s_noTag, 0
},
{"callInformationRequest", true, 45,
s_sequenceTag, s_callInformationRequestArgs,
s_noTag, 0
},
{"sendChargingInformation", true, 46,
s_sequenceTag, s_sendChargingInformationArgs,
s_noTag, 0
},
{"playAnnouncement", true, 47,
s_sequenceTag, s_playAnnouncementArgs,
s_noTag, 0
},
{"promptAndCollectUserInformation", true, 48,
s_sequenceTag, s_promptAndCollectUserInformationArgs,
s_noTag, 0
},
{"specializedResourceReport", true, 49,
s_noTag, 0,
s_noTag, 0
},
{"cancel", true, 53,
s_noTag, s_cancelChoice,
s_noTag, 0
},
{"activityTest", true, 55,
s_noTag, 0,
s_noTag, 0
},
{"", false, 0,
s_noTag, 0,
s_noTag, 0
},
};
const TokenDict s_unknownSubscriberDiagnostic[] = {
{"imsiUnknown", 0},
{"gprsSubscriptionUnknown", 1},
{0, 0},
};
const TokenDict s_roamingNotAllowedCause[] = {
{"plmnRoamingNotAllowed", 0},
{"operatorDeterminedBarring", 3},
{0, 0},
};
const TokenDict s_absentSubscriberReason[] = {
{"imsiDetach", 0 },
{"restrictedArea", 1 },
{"noPageResponse", 2 },
{0, 0},
};
const TokenDict s_smDeliveryFailureCause[] = {
{"memoryCapacityExceeded", 0 },
{"equipmentProtocolError", 1 },
{"equipmentNotSM-Equipped ", 2 },
{"unknownServiceCentre", 3 },
{"sc-Congestion", 4 },
{"invalidSME-Address", 5 },
{"subscriberNotSC-Subscriber", 6 },
{0, 0},
};
const TokenDict s_networkResource[] = {
{"plmn", 0 },
{"hlr", 1 },
{"vlr ", 2 },
{"pvlr", 3 },
{"controllingMSC", 4 },
{"vmsc", 5 },
{"eir", 6 },
{"rss", 7 },
{0, 0},
};
const Parameter s_extensibleSystemFailure[] = {
{"networkResource", s_enumTag, true, TcapXApplication::Enumerated, s_networkResource},
{"extensionContainer", s_sequenceTag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
const Parameter s_systemFailure[] = {
{"networkResource", s_enumTag, false, TcapXApplication::Enumerated, s_networkResource},
{"extensibleSystemFailure", s_sequenceTag, false, TcapXApplication::Sequence, s_extensibleSystemFailure},
{"", s_noTag, false, TcapXApplication::None, 0},
};
const TokenDict s_pwRegistrationFailureCause[] = {
{"undetermined", 0 },
{"invalidFormat", 1 },
{"newPasswordsMismatch", 2 },
{0, 0},
};
const TokenDict s_callBarringCause[] = {
{"barringServiceActive", 0 },
{"operatorBarring", 1 },
{0, 0},
};
const Parameter s_extensibleCallBarredParam[] = {
{"callBarringCause", s_enumTag, true, TcapXApplication::Enumerated, s_callBarringCause},
{"extensionContainer", s_sequenceTag, true, TcapXApplication::HexString, 0},
{"unauthorisedMessageOriginator", s_nullTag, true, TcapXApplication::Null, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_unknownSubscriberErr[] = {
{"extensionContainer", s_sequenceTag, true, TcapXApplication::HexString, 0},
{"unknownSubscriberDiagnostic", s_enumTag, true, TcapXApplication::Enumerated, s_unknownSubscriberDiagnostic},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_absentsubscriberSMErr[] = {
{"absentSubscriberDiagnosticSM", s_intTag, true, TcapXApplication::Integer, 0},
{"extensionContainer", s_sequenceTag, true, TcapXApplication::HexString, 0},
{"additionalAbsentSubscriberDiagnosticSM", s_intTag, true, TcapXApplication::Integer, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_roamingNotAllowedErr[] = {
{"roamingNotAllowedCause", s_enumTag, true, TcapXApplication::Enumerated, s_roamingNotAllowedCause},
{"extensionContainer", s_sequenceTag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_callBarredErr[] = {
{"callBarringCause", s_enumTag, true, TcapXApplication::Enumerated, s_callBarringCause},
{"extensibleCallBarredParam", s_sequenceTag, true, TcapXApplication::Sequence, s_extensibleCallBarredParam},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_ssIncompatibilityErr[] = {
{"ss-Code", s_ctxtPrim_1_Tag, true, TcapXApplication::Enumerated, s_SSCode},
{"basicService", s_noTag, true, TcapXApplication::Choice, s_basicServiceCode},
{"ss-Status", s_ctxtPrim_4_Tag, true, TcapXApplication::Flags, s_ssStatus},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_absentSubscriberErr[] = {
{"extensionContainer", s_sequenceTag, true, TcapXApplication::HexString, 0},
{"absentSubscriberReason", s_ctxtPrim_0_Tag, true, TcapXApplication::Enumerated, s_absentSubscriberReason},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_smDeliveryFailureErr[] = {
{"sm-EnumeratedDeliveryFailureCause", s_enumTag, true, TcapXApplication::Enumerated, s_smDeliveryFailureCause},
{"diagnosticInfo", s_hexTag, true, TcapXApplication::HexString, 0},
{"extensionContainer", s_sequenceTag, true, TcapXApplication::HexString, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_systemFailureErr[] = {
{"systemFailureParam", s_noTag, true, TcapXApplication::Choice, s_systemFailure},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_pwRegistrationFailureErr[] = {
{"pw-RegistrationFailureCause", s_enumTag, true, TcapXApplication::Enumerated, s_pwRegistrationFailureCause},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Parameter s_busySubscriberErr[] = {
{"extensionContainer", s_sequenceTag, true, TcapXApplication::HexString, 0},
{"ccbs-Possible", s_ctxtPrim_0_Tag, true, TcapXApplication::Null, 0},
{"ccbs-Busy", s_ctxtPrim_1_Tag, true, TcapXApplication::Null, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Operation s_mapErrors[] = {
{"unknownSubscriber", true, 1,
s_sequenceTag, s_unknownSubscriberErr,
s_noTag, 0
},
{"unknownMSC", true, 3,
s_noTag, 0,
s_noTag, 0
},
{"unidentifiedSubscriber", true, 5,
s_sequenceTag, s_extensionContainerRes,
s_noTag, 0
},
{"absentsubscriberSM", true, 6,
s_sequenceTag, s_absentsubscriberSMErr,
s_noTag, 0
},
{"unknownEquipment", true, 7,
s_noTag, 0,
s_noTag, 0
},
{"roamingNotAllowed", true, 8,
s_sequenceTag, s_roamingNotAllowedErr,
s_noTag, 0
},
{"illegalSubscriber", true, 9,
s_sequenceTag, s_extensionContainerRes,
s_noTag, 0
},
{"bearerServiceNotProvisioned", true, 10,
s_sequenceTag, s_extensionContainerRes,
s_noTag, 0
},
{"teleserviceNotProvisioned", true, 11,
s_sequenceTag, s_extensionContainerRes,
s_noTag, 0
},
{"illegalEquipment", true, 12,
s_sequenceTag, s_extensionContainerRes,
s_noTag, 0
},
{"callBarred", true, 13,
s_noTag, s_callBarredErr,
s_noTag, 0
},
{"forwardingViolation", true, 14,
s_sequenceTag, s_extensionContainerRes,
s_noTag, 0
},
{"illegalSS-Operation", true, 16,
s_noTag, 0,
s_noTag, 0
},
{"ss-ErrorStatus", true, 17,
s_noTag, 0,
s_noTag, 0
},
{"ss-NotAvailable", true, 18,
s_noTag, 0,
s_noTag, 0
},
{"ss-SubscriptionViolation", true, 19,
s_noTag, 0,
s_noTag, 0
},
{"ss-Incompatibility", true, 20,
s_sequenceTag, s_ssIncompatibilityErr,
s_noTag, 0
},
{"facilityNotSupported", true, 21,
s_sequenceTag, s_extensionContainerRes,
s_noTag, 0
},
{"absentSubscriber", true, 27,
s_sequenceTag, s_absentSubscriberErr,
s_noTag, 0
},
{"sm-DeliveryFailure", true, 32,
s_sequenceTag, s_smDeliveryFailureErr,
s_noTag, 0
},
{"messageWaitingListFull", true, 33,
s_sequenceTag, s_extensionContainerRes,
s_noTag, 0
},
{"systemFailure", true, 34,
s_noTag, s_systemFailure,
s_noTag, 0
},
{"dataMissing", true, 35,
s_sequenceTag, s_extensionContainerRes,
s_noTag, 0
},
{"unexpectedDataValue", true, 36,
s_sequenceTag, s_extensionContainerRes,
s_noTag, 0
},
{"pw-RegistrationFailure", true, 37,
s_noTag, s_pwRegistrationFailureErr,
s_noTag, 0
},
{"negativePW-Check", true, 38,
s_noTag, 0,
s_noTag, 0
},
{"noRoamingNumberAvailable", true, 39,
s_sequenceTag, s_extensionContainerRes,
s_noTag, 0
},
{"tracingBufferFull", true, 40,
s_sequenceTag, s_extensionContainerRes,
s_noTag, 0
},
{"numberOfPW-AttemptsViolation", true, 43,
s_noTag, 0,
s_noTag, 0
},
{"busySubscriber", true, 45,
s_sequenceTag, s_busySubscriberErr,
s_noTag, 0
},
{"noSubscriberReply", true, 46,
s_sequenceTag, s_extensionContainerRes,
s_noTag, 0
},
{"or-NotAllowed", true, 48,
s_sequenceTag, s_extensionContainerRes,
s_noTag, 0
},
{"ati-NotAllowed", true, 49,
s_sequenceTag, s_extensionContainerRes,
s_noTag, 0
},
{"resourceLimitation", true, 51,
s_sequenceTag, s_extensionContainerRes,
s_noTag, 0
},
{"unauthorizedRequestingNetwork", true, 52,
s_sequenceTag, s_extensionContainerRes,
s_noTag, 0
},
{"unknownAlphabet", true, 71,
s_noTag, 0,
s_noTag, 0
},
{"ussd-Busy", true, 72,
s_noTag, 0,
s_noTag, 0
},
{"", false, 0,
s_noTag, 0,
s_noTag, 0
},
};
static const TokenDict s_problemEnum[] = {
{"unknownOperation", 0x00},
{"tooLate", 0x01},
{"operationNotCancellable", 0x02},
{"", 0xff},
};
static const Parameter s_cancelFailedErr[] = {
{"problem", s_ctxtPrim_0_Tag, false, TcapXApplication::Enumerated, s_problemEnum},
{"operation", s_ctxtPrim_1_Tag, false, TcapXApplication::Integer, 0},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_requestedInfoEnum[] = {
{"unknownRequestedInfo", 0x01},
{"requestedInfoNotAvailable", 0x02},
{"", 0xff},
};
static const Parameter s_requestedInfoErr[] = {
{"requestedInfoError", s_enumTag, false, TcapXApplication::Enumerated, s_requestedInfoEnum},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_systemFailureEnum[] = {
{"unavailableResources", 0x00},
{"componentFailure", 0x01},
{"basicCallProcessingException", 0x02},
{"resourceStatusFailure", 0x03},
{"endUserFailure", 0x04},
{"", 0xff},
};
static const Parameter s_systemFailureCamelErr[] = {
{"systemFailureError", s_enumTag, false, TcapXApplication::Enumerated, s_systemFailureEnum},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const TokenDict s_taskRefusedEnum[] = {
{"generic", 0x00},
{"unobtainable", 0x01},
{"congestion", 0x02},
{"", 0xff},
};
static const Parameter s_taskRefusedErr[] = {
{"taskRefusedError", s_enumTag, false, TcapXApplication::Enumerated, s_taskRefusedEnum},
{"", s_noTag, false, TcapXApplication::None, 0},
};
static const Operation s_camelErrors[] = {
{"cancelled", true, 0,
s_noTag, 0,
s_noTag, 0
},
{"cancelFailed", true, 1,
s_sequenceTag, s_cancelFailedErr,
s_noTag, 0
},
{"eTCFailed", true, 3,
s_noTag, 0,
s_noTag, 0
},
{"improperCallerResponse", true, 4,
s_noTag, 0,
s_noTag, 0
},
{"missingCustomerRecord", true, 6,
s_noTag, 0,
s_noTag, 0
},
{"missingParameter", true, 7,
s_noTag, 0,
s_noTag, 0
},
{"parameterOutOfRange", true, 8,
s_noTag, 0,
s_noTag, 0
},
{"requestedInfoError", true, 10,
s_noTag, s_requestedInfoErr,
s_noTag, 0
},
{"systemFailure", true, 11,
s_noTag, s_systemFailureCamelErr,
s_noTag, 0
},
{"taskRefused", true, 12,
s_noTag, s_taskRefusedErr,
s_noTag, 0
},
{"unavailableResource", true, 13,
s_noTag, 0,
s_noTag, 0
},
{"unexpectedComponentSequence", true, 14,
s_noTag, 0,
s_noTag, 0
},
{"unexpectedDataValue", true, 15,
s_noTag, 0,
s_noTag, 0
},
{"unexpectedParameter", true, 16,
s_noTag, 0,
s_noTag, 0
},
{"unknownLegID", true, 17,
s_noTag, 0,
s_noTag, 0
},
{"", false, 0,
s_noTag, 0,
s_noTag, 0
},
};
static const TokenDict s_appStates[] = {
{"waiting", TcapXApplication::Waiting},
{"active", TcapXApplication::Active},
{"shutdown", TcapXApplication::ShutDown},
{"inactive", TcapXApplication::Inactive},
{"", 0},
};
static const TokenDict s_userTypes[] = {
{"MAP", TcapXUser::MAP},
{"CAMEL", TcapXUser::CAMEL},
{"", 0},
};
static void replace(String& str, char what, char with)
{
char* c = (char*)str.c_str();
while (c && *c) {
if(*c == what)
*c = with;
c++;
}
}
static const Operation* findError(TcapXUser::UserType type, int opCode, bool opLocal = true)
{
DDebug(&__plugin,DebugAll,"findError(opCode=%d, local=%s)",opCode,String::boolText(opLocal));
const Operation* ops = (type == TcapXUser::MAP ? s_mapErrors : s_camelErrors);
while (!TelEngine::null(ops->name)) {
if (ops->code == opCode && ops->local == opLocal)
return ops;
ops++;
}
return 0;
}
static const Operation* findError(TcapXUser::UserType type, const String& op)
{
DDebug(&__plugin,DebugAll,"findError(opCode=%s)",op.c_str());
const Operation* ops = (type == TcapXUser::MAP ? s_mapOps : s_camelOps);
while (!TelEngine::null(ops->name)) {
if (op == ops->name)
return ops;
ops++;
}
return 0;
}
static const Operation* findOperation(TcapXUser::UserType type, int opCode, bool opLocal = true)
{
DDebug(&__plugin,DebugAll,"findOperation(type=%s,opCode=%d, local=%s)",lookup(type,s_userTypes),opCode,String::boolText(opLocal));
const Operation* ops = (type == TcapXUser::MAP ? s_mapOps : s_camelOps);
while (!TelEngine::null(ops->name)) {
if (ops->code == opCode && ops->local == opLocal)
return ops;
ops++;
}
return 0;
}
static const Operation* findOperation(TcapXUser::UserType type, const String& op)
{
DDebug(&__plugin,DebugAll,"findOperation(opCode=%s)",op.c_str());
const Operation* ops = (type == TcapXUser::MAP ? s_mapOps : s_camelOps);
while (!TelEngine::null(ops->name)) {
if (op == ops->name)
return ops;
ops++;
}
return 0;
}
static const Capability* findCapability(TcapXUser::UserType type, const String& opName)
{
DDebug(&__plugin,DebugAll,"findCapability(opName=%s)",opName.c_str());
const Capability* cap = (type == TcapXUser::MAP ? s_mapCapab : s_camelCapab);
while (cap->name) {
int index = 0;
while (!TelEngine::null(cap->ops[index])) {
if (opName == cap->ops[index])
return cap;
index++;
}
cap++;
}
return 0;
}
static bool findDefCapability(TcapXUser::UserType type, const String& cap)
{
DDebug(&__plugin,DebugAll,"findDefCapability(opName=%s)",cap.c_str());
const Capability* caps = (type == TcapXUser::MAP ? s_mapCapab : s_camelCapab);
while (caps->name) {
if (cap == caps->name)
return true;
caps++;
}
return false;
}
static const AppCtxt* findCtxtFromOid(TcapXUser::UserType type, const String& oid)
{
DDebug(&__plugin,DebugAll,"findCtxtFromOid(oid=%s)",oid.c_str());
const AppCtxt* ctxt = (type == TcapXUser::MAP ? s_mapAppCtxt : s_camelAppCtxt);
while (ctxt->name) {
if (oid == ctxt->oid)
return ctxt;
ctxt++;
}
return 0;
}
static const AppCtxt* findCtxtFromStr(TcapXUser::UserType type, const String& oid)
{
DDebug(&__plugin,DebugAll,"findCtxtFromStr(ctxt=%s)",oid.c_str());
const AppCtxt* ctxt = (type == TcapXUser::MAP ? s_mapAppCtxt : s_camelAppCtxt);
while (ctxt->name) {
if (oid == ctxt->name)
return ctxt;
ctxt++;
}
return 0;
}
/**
* IDMap
*/
void IDMap::appendID(const char* tcapID, const char* appID)
{
DDebug(&__plugin,DebugAll,"IDMap::appendID(tcapID=%s,appID=%s)",tcapID,appID);
if (tcapID && appID)
append(new NamedString(appID,tcapID));
}
const String& IDMap::findTcapID(const char* appID)
{
DDebug(&__plugin,DebugAll,"IDMap::findTcapID(appID=%s)",appID);
ObjList* obj = find(appID);
if (obj) {
NamedString* ns = static_cast<NamedString*>(obj->get());
if (!TelEngine::null(ns))
return (*ns);
}
return String::empty();
}
const String& IDMap::findAppID(const char* tcapID)
{
DDebug(&__plugin,DebugAll,"IDMap::findAppID(tcapID=%s)",tcapID);
for (ObjList* o = skipNull(); o; o = o->skipNext()) {
NamedString* ns = static_cast<NamedString*>(o->get());
if (!TelEngine::null(ns) && (*ns) == tcapID)
return ns->name();
}
return String::empty();
}
void IDMap::removeAppID(const char* appID)
{
DDebug(&__plugin,DebugAll,"IDMap::removeAppID(appID=%s)",appID);
remove(appID);
}
/**
* XMLConnection
*/
XMLConnection::XMLConnection(Socket* skt, TcapXApplication* app)
: Thread("XMLConnection"),
m_socket(skt), m_app(app)
{
Debug(&__plugin,DebugAll,"XMLConnection created with socket=[%p] for application=%s[%p] [%p]",socket,app->toString().c_str(),app,this);
m_parser = new XmlDomParser(app->toString() + "Parser",true);
m_app->ref();
start();
}
XMLConnection::~XMLConnection()
{
Debug(&__plugin,DebugAll,"XMLConnection destroyed [%p]",this);
if (m_parser) {
delete m_parser;
m_parser = 0;
}
if (m_socket){
delete m_socket;
m_socket = 0;
}
TelEngine::destruct(m_app);
}
void XMLConnection::start()
{
Debug(&__plugin,DebugAll,"XMLConnection start [%p]",this);
m_socket->setBlocking(false);
}
void XMLConnection::run()
{
if (!m_socket)
return;
char buffer[2048];
bool print = false;
for (;;) {
if (!(m_socket && m_socket->valid() && m_parser))
break;
Thread::check();
bool readOk = false, error = false;
if (!m_socket->select(&readOk,0,&error,idleUsec()))
continue;
if (!readOk || error) {
if (error) {
Debug(&__plugin,DebugInfo,"XMLConnection[%p] : Reading data error: %s (%d)",this,strerror(m_socket->error()),
m_socket->error());
return;
}
continue;
}
int readSize = m_socket->readData(buffer,sizeof(buffer));
if (!readSize) {
if (m_socket->canRetry()) {
idle(true);
continue;
}
return;
}
else if (readSize < 0) {
if (m_socket->canRetry()) {
idle(true);
continue;
}
cancel();
Debug(&__plugin,DebugWarn,"Read error %s(%d) on socket %p in XMLConnection[%p]",strerror(m_socket->error()),
m_socket->error(),m_socket,this);
break;
}
buffer[readSize] = 0;
XDebug(&__plugin,DebugAll,"READ %d : %s",readSize,buffer);
int bufferSize = readSize;
while (bufferSize) {
int len = bufferSize;
char* end = strstr(buffer,"</m>");
if (end) {
len = end + strlen("</m>") - buffer + 1;
if (len > bufferSize)
len = bufferSize;
}
String str(buffer,len);
bufferSize -= len;
if (!m_parser)
break;
XDebug(&__plugin,DebugAll,"PUSH = %d, REST = %d, TOTAL = %d, push to parser %s",len,bufferSize,readSize,str.c_str());
if(!m_parser->parse(str)) {
if (m_parser->error() != XmlSaxParser::Incomplete) {
print = true;
Debug(&__plugin,DebugWarn,"Parser error %s in read data [%p] unparsed type %d, buffer = %s, pushed = %s",
m_parser->getError(),this,m_parser->unparsed(),m_parser->getBuffer().c_str(),str.c_str());
}
}
else {
XmlFragment* frag = m_parser->fragment();
if (frag && frag->findElement(frag->getChildren().skipNull(),&s_msgTag,0,false) && m_app)
m_app->receivedXML(frag);
}
::memmove(buffer,buffer + len,bufferSize + 1);
}
}
}
void XMLConnection::cleanup()
{
DDebug(&__plugin,DebugAll,"XMLConnection::cleanup() [%p]",this);
m_app->setIO(0);
}
bool XMLConnection::writeData(XmlFragment* elem)
{
if (!elem)
return false;
String xml;
elem->toString(xml,true);
XDebug(&__plugin,DebugAll,"WRITE : %s",xml.c_str());
int len = xml.length();
const char* buffer = xml.c_str();
while (m_socket && (len > 0)) {
bool writeOk = false,error = false;
if (!m_socket->select(0,&writeOk,&error,idleUsec()))
continue;
if (!writeOk || error)
continue;
int w = m_socket->writeData(buffer,len);
if (w < 0) {
if (!m_socket->canRetry()) {
Debug(&__plugin,DebugWarn,"XMLConnection::writeData(xml=[%p]) [%p] on socket [%p] could not write error : %s",
elem,this,m_socket,strerror(m_socket->error()));
cancel();
return false;
}
}
else {
buffer += w;
len -= w;
}
}
return true;
}
/**
* XMLConnListener
*/
XMLConnListener::XMLConnListener(TcapXUser* user, const NamedList& sect)
: Thread("XMLConnListener"),
m_user(user)
{
Debug(&__plugin,DebugAll,"XMLConnListener [%p] created",this);
m_host = sect.getValue(YSTRING("host"),"127.0.0.1");
m_port = sect.getIntValue(YSTRING("port"),5555);
}
XMLConnListener::~XMLConnListener()
{
Debug(&__plugin,DebugAll,"XMLConnListener [%p] destroyed",this);
m_user = 0;
}
bool XMLConnListener::init()
{
SocketAddr addr;
if (!addr.assign(AF_INET) || !addr.host(m_host) || !addr.port(m_port)) {
Debug(m_user,DebugWarn,"Could not assign address=%s:%d for user listener=%s [%p]",m_host.c_str(),m_port,
m_user->toString().c_str(),this);
return false;
}
if (!m_socket.create(addr.family(),SOCK_STREAM)) {
Debug(m_user,DebugWarn, "Could not create socket for user listener=%s [%p] error %d: %s",
m_user->toString().c_str(),this,m_socket.error(),strerror(m_socket.error()));
return false;
}
m_socket.setReuse();
if (!m_socket.bind(addr)) {
Debug(m_user,DebugWarn,"Could not bind user listener=%s [%p] error %d: %s",
m_user->toString().c_str(),this,m_socket.error(),strerror(m_socket.error()));
return false;
}
if (!m_socket.setBlocking(false) || !m_socket.listen())
return false;
return startup();
}
void XMLConnListener::run()
{
for (;;) {
Thread::check();
idle();
SocketAddr address;
Socket* newSocket = m_socket.accept(address);
if (!newSocket) {
if (m_socket.canRetry())
continue;
Debug(m_user,DebugWarn,"Accept error: %s",strerror(m_socket.error()));
break;
}
else {
String addr(address.host());
addr << ":" << address.port();
if (!createConn(newSocket,addr))
Debug(m_user,DebugInfo,"Connection from %s rejected",addr.c_str());
}
}
}
bool XMLConnListener::createConn(Socket* skt, String& addr)
{
if (!skt->valid()) {
delete skt;
return false;
}
if (!skt->setBlocking(false)) {
Debug(m_user,DebugGoOn, "Failed to set TCP socket to nonblocking mode: %s",
strerror(skt->error()));
delete skt;
return false;
}
if (m_user && !m_user->createApplication(skt,addr)) {
delete skt;
return false;
}
return true;
}
void XMLConnListener::cleanup()
{
DDebug(m_user,DebugAll,"XMLConnListener::cleanup() [%p]",this);
m_user->setListener(0);
}
/**
* TcapToXml
*/
const XMLMap TcapToXml::s_xmlMap[] = {
{Regexp("^state$"), "state", "", TcapToXml::Value},
{Regexp("^error$"), "error", "", TcapToXml::Value},
{Regexp("^LocalPC$"), "transport.mtp", "", TcapToXml::Element},
{Regexp("^RemotePC$"), "transport.mtp", "", TcapToXml::Element},
{Regexp("^sls$"), "transport.mtp", "", TcapToXml::Element},
{Regexp("^ReturnCause$"), "transport.sccp", "ReturnCause", TcapToXml::Element},
{Regexp("^CallingPartyAddress\\.gt\\.encoding$"), "transport.sccp.CallingPartyAddress.gt", "encoding", TcapToXml::Attribute},
{Regexp("^CallingPartyAddress\\.gt\\.np$"), "transport.sccp.CallingPartyAddress.gt", "plan", TcapToXml::Attribute},
{Regexp("^CallingPartyAddress\\.gt\\.nai$"), "transport.sccp.CallingPartyAddress.gt", "nature", TcapToXml::Attribute},
{Regexp("^CallingPartyAddress\\.gt\\.tt$"), "transport.sccp.CallingPartyAddress.gt", "translation", TcapToXml::Attribute},
{Regexp("^CallingPartyAddress\\.gt$"), "transport.sccp.CallingPartyAddress", "gt", TcapToXml::Element},
{Regexp("^CallingPartyAddress\\.ssn$"), "transport.sccp.CallingPartyAddress", "ssn", TcapToXml::Element},
{Regexp("^CallingPartyAddress\\.route$"), "transport.sccp.CallingPartyAddress", "route", TcapToXml::Element},
{Regexp("^CallingPartyAddress\\.pointcode$"), "transport.sccp.CallingPartyAddress", "pointcode", TcapToXml::Element},
{Regexp("^CallingPartyAddress\\..\\+$"), "transport.sccp.CallingPartyAddress", "", TcapToXml::Element},
{Regexp("^CalledPartyAddress\\.gt\\.encoding$"), "transport.sccp.CalledPartyAddress.gt", "encoding", TcapToXml::Attribute},
{Regexp("^CalledPartyAddress\\.gt\\.np$"), "transport.sccp.CalledPartyAddress.gt", "plan", TcapToXml::Attribute},
{Regexp("^CalledPartyAddress\\.gt\\.nai$"), "transport.sccp.CalledPartyAddress.gt", "nature", TcapToXml::Attribute},
{Regexp("^CalledPartyAddress\\.gt\\.tt$"), "transport.sccp.CalledPartyAddress.gt", "translation", TcapToXml::Attribute},
{Regexp("^CalledPartyAddress\\.gt$"), "transport.sccp.CalledPartyAddress", "gt", TcapToXml::Element},
{Regexp("^CalledPartyAddress\\.ssn$"), "transport.sccp.CalledPartyAddress", "ssn", TcapToXml::Element},
{Regexp("^CalledPartyAddress\\.route$"), "transport.sccp.CalledPartyAddress", "route", TcapToXml::Element},
{Regexp("^CalledPartyAddress\\.pointcode$"), "transport.sccp.CalledPartyAddress", "pointcode", TcapToXml::Element},
{Regexp("^CalledPartyAddress\\..\\+$"), "transport.sccp.CalledPartyAddress", "", TcapToXml::Element},
{Regexp("^tcap\\.request\\.type$"), "transport.tcap", "request-type", TcapToXml::Element},
{Regexp("^tcap\\.transaction\\.localTID$"), "transport.tcap", "localTID", TcapToXml::Element},
{Regexp("^tcap\\.transaction\\.remoteTID$"), "transport.tcap", "remoteTID", TcapToXml::Element},
{Regexp("^tcap\\.transaction\\.abort\\.cause$"), "transport.tcap", "abort-cause", TcapToXml::Element},
{Regexp("^tcap\\.transaction\\.abort\\.information$"), "transport.tcap", "abort-information", TcapToXml::Element},
{Regexp("^tcap\\.transaction\\..\\+$"), "transport.tcap", "", TcapToXml::Element},
{Regexp("^tcap\\.dialogPDU\\.application-context-name$"), "application", "", TcapToXml::Value},
{Regexp("^tcap\\.dialogPDU\\.dialog-pdu-type$"), "transport.tcap.dialog", "type", TcapToXml::Attribute},
{Regexp("^tcap\\.dialogPDU\\.abort-source$"), "transport.tcap.dialog", "abort-source", TcapToXml::Element},
{Regexp("^tcap\\.dialogPDU\\.result$"), "transport.tcap.dialog", "result", TcapToXml::Element},
{Regexp("^tcap\\.dialogPDU\\.result-source-diagnostic$"), "transport.tcap.dialog", "result-source-diagnostic", TcapToXml::Element},
{Regexp("^tcap\\.dialogPDU\\.userInformation\\.direct-reference$"), "transport.tcap.dialog.userInformation", "direct-reference", TcapToXml::Element},
{Regexp("^tcap\\.dialogPDU\\.userInformation\\.encoding-contents$"),"transport.tcap.dialog.userInformation", "encoding-contents",TcapToXml::Element},
{Regexp("^tcap\\.dialogPDU\\.userInformation\\.encoding-type$"), "transport.tcap.dialog.userInformation", "encoding-type", TcapToXml::Element},
{Regexp("^tcap\\.dialogPDU\\.userInformation\\..\\+$"), "transport.tcap.dialog.userInformation", "", TcapToXml::Element},
{Regexp("^tcap\\.component\\.count$"), "", "", TcapToXml::None},
{Regexp("^tcap\\.component\\..\\+\\.localCID$"), "component", "", TcapToXml::Attribute},
{Regexp("^tcap\\.component\\..\\+\\.remoteCID$"), "component", "", TcapToXml::Attribute},
{Regexp("^tcap\\.component\\..\\+\\.componentType$"), "component", "type", TcapToXml::Attribute},
{Regexp("^tcap\\.component\\..\\+\\.operationCode$"), "component", "", TcapToXml::Attribute},
{Regexp("^tcap\\.component\\..\\+\\.operationCodeType$"), "", "", TcapToXml::None},
{Regexp("^tcap\\.component\\..\\+\\.errorCode$"), "component", "", TcapToXml::Attribute},
{Regexp("^tcap\\.component\\..\\+\\.errorCodeType$"), "", "", TcapToXml::None},
{Regexp("^tcap\\.component\\..\\+\\.problemCode$"), "component", "", TcapToXml::Attribute},
{Regexp("^tcap\\.component\\..\\+\\..\\+"), "component", "", TcapToXml::Element},
{Regexp(""), "", "", TcapToXml::End},
};
TcapToXml::TcapToXml(TcapXApplication* app)
: Mutex(false,"TcapToXml"),
m_app(app), m_type(Unknown)
{
DDebug(&__plugin,DebugAll,"TcapToXml created for application=%s[%p] [%p]",m_app->toString().c_str(),m_app,this);
}
TcapToXml::~TcapToXml()
{
DDebug(&__plugin,DebugAll,"TcapToXml destroyed [%p]",this);
reset();
}
void TcapToXml::reset()
{
m_type = Unknown;
}
const XMLMap* TcapToXml::findMap(String& what)
{
XDebug(&__plugin,DebugAll,"TcapToXml::findMap(%s) [%p]",what.c_str(),this);
const XMLMap* map = s_xmlMap;
while (map->type != End) {
if (what.matches(map->name))
return map;
map++;
}
return 0;
}
bool TcapToXml::buildXMLMessage(NamedList& params, XmlFragment* msg, MsgType type)
{
DDebug(&__plugin,DebugAll,"TcapToXML::buildXMLMessage() [%p]",this);
if (!msg)
return false;
XmlDeclaration* decl = new XmlDeclaration();
msg->addChild(decl);
XmlElement* el = new XmlElement(s_msgTag);
el->setXmlns("",true,s_namespace);
msg->addChild(el);
AppCtxt* appCtxt = 0;
NamedString* ctxt = params.getParam(s_tcapAppCtxt);
if (!TelEngine::null(ctxt))
appCtxt = (AppCtxt*)findCtxtFromOid(m_app->type(),*ctxt);
if (appCtxt)
params.setParam(s_tcapAppCtxt,appCtxt->name);
// translate P-Abort causes
ctxt = params.getParam(s_tcapAbortCause);
if (!TelEngine::null(ctxt) && (*ctxt) == "pAbort") {
int code = params.getIntValue(s_tcapAbortInfo);
params.setParam(s_tcapAbortInfo,lookup(code,SS7TCAPError::s_errorTypes,*ctxt));
}
for (unsigned int i = 0; i < params.count(); i++) {
NamedString* ns = params.getParam(i);
if (TelEngine::null(ns))
continue;
if (ns->name().startsWith(s_tcapCompPrefixSep))
continue;
const XMLMap* map = findMap((String&)ns->name());
if (!map)
continue;
addToXml(el,map,ns);
}
addComponentsToXml(el,params,appCtxt);
return true;
}
void TcapToXml::addToXml(XmlElement* root, const XMLMap* map, NamedString* val)
{
if (!(root && map && !TelEngine::null(val)))
return;
if (map->type == None)
return;
XDebug(&__plugin,DebugAll,"TcapToXml::addToXml(frag=%p, map=%s[%p], val=%s[%p]) [%p]",root,map->map,map,val->name().c_str(),val,this);
String mapStr = map->map;
ObjList* path = mapStr.split('.',false);
XmlElement* parent = root;
for (ObjList* o = path->skipNull(); o; o = o->skipNext()) {
String* elem = static_cast<String*>(o->get());
if (TelEngine::null(elem))
continue;
XmlElement* child = parent->findFirstChild(elem);
if (!child) {
child = new XmlElement(*elem);
parent->addChild(child);
}
parent = child;
}
if (parent) {
// add to parent child element if map is elem, or attr if map si attribute
XmlElement* child = 0;
String tag;
if (TelEngine::null(map->tag)) {
tag = val->name();
if (tag.find('.') > -1 && tag.startsWith(map->name))
tag.startSkip(map->name,false);
replace(tag,'.','-');
}
else
tag = map->tag;
switch (map->type) {
case Element:
child = new XmlElement(tag);
child->addText(*val);
parent->addChild(child);
break;
case Value:
parent->addText(*val);
break;
case Attribute:
parent->setAttributeValid(tag,*val);
break;
case None:
default:
break;
}
}
TelEngine::destruct(path);
}
void TcapToXml::addComponentsToXml(XmlElement* el, NamedList& params, AppCtxt* ctxt)
{
if (!el)
return;
DDebug(&__plugin,DebugAll,"TcapToXml::addComponentsToXml(el=%p, params=%p) [%p]",el,&params,this);
int count = params.getIntValue(s_tcapCompCount);
for (int i = 1; i <= count; i++) {
XmlElement* comp = new XmlElement(s_component);
el->addChild(comp);
String root;
root << s_tcapCompPrefix << "." << String(i);
NamedList compParams("");
compParams.copyParam(params,root,'.');
NamedString* opCode = params.getParam(root + "." + s_tcapOpCode);
NamedString* opType = params.getParam(root + "." + s_tcapOpCodeType);
Operation* op = 0;
if (!TelEngine::null(opCode) && !TelEngine::null(opType))
op = (Operation*)findOperation(m_app->type(),opCode->toInteger(),(*opType == "local" ? true : false));
if (op)
compParams.setParam(root + "." + s_tcapOpCode,op->name);
int compType = SS7TCAP::lookupComponent(params.getValue(root + "." + s_tcapCompType));
bool searchArgs = true;
switch (compType) {
case SS7TCAP::TC_Invoke:
case SS7TCAP::TC_ResultLast:
case SS7TCAP::TC_ResultNotLast:
searchArgs = (compType == SS7TCAP::TC_Invoke);
break;
case SS7TCAP::TC_U_Error:
opCode = params.getParam(root + "." + s_tcapErrCode);
opType = params.getParam(root + "." + s_tcapErrCodeType);
if (!TelEngine::null(opCode) && !TelEngine::null(opType))
op = (Operation*)findError(m_app->type(),opCode->toInteger(),(*opType == "local" ? true : false));
if (op)
compParams.setParam(root + "." + s_tcapErrCode,op->name);
break;
case SS7TCAP::TC_R_Reject:
case SS7TCAP::TC_U_Reject:
case SS7TCAP::TC_L_Reject:
compParams.setParam(root + "." + s_tcapProblemCode,
lookup(params.getIntValue(root + "." + s_tcapProblemCode),SS7TCAPError::s_errorTypes));
break;
default:
break;
}
for (unsigned int j = 0; j < compParams.count(); j++) {
NamedString* ns = compParams.getParam(j);
if (TelEngine::null(ns))
continue;
const XMLMap* map = findMap((String&)ns->name());
if (!map)
continue;
XmlElement* child;
int pos = ns->name().rfind('.');
String tag = ns->name().substr(pos + 1);
tag = (TelEngine::null(map->tag) ? tag : (String)map->tag);
switch (map->type) {
case Element:
child = new XmlElement(tag);
child->addText(*ns);
comp->addChild(child);
break;
case Value:
comp->addText(*ns);
break;
case Attribute:
comp->setAttributeValid(tag,*ns);
break;
case None:
default:
break;
}
}
NamedString* payloadHex = params.getParam(root);
if (TelEngine::null(payloadHex))
continue;
addParametersToXml(comp,*payloadHex,op,searchArgs);
}
}
void TcapToXml::addParametersToXml(XmlElement* elem, String& payloadHex, Operation* op, bool searchArgs)
{
if (!elem)
return;
DDebug(&__plugin,DebugAll,"TcapToXml::addParametersToXml(elem=%s[%p], payload=%s, op=%s[%p], searchArgs=%s) [%p]",
elem->getTag().c_str(),elem,payloadHex.c_str(),(op ? op->name.c_str() : ""),op,String::boolText(searchArgs),this);
DataBlock data;
if (!data.unHexify(payloadHex.c_str(),payloadHex.length(),' ')) {
DDebug(&__plugin,DebugAll,"TcapToXml::addParamtersToXml() invalid hexified payload=%s [%p]",payloadHex.c_str(),this);
return;
}
if (elem->getTag() == s_component) {
AsnTag tag = (op ? (searchArgs ? op->argTag : op->retTag) : s_noTag);
AsnTag decTag;
AsnTag::decode(decTag,data);
if (op && tag != decTag) {
if (tag != s_noTag)
op = 0;
}
if (decTag.type() == AsnTag::Constructor && tag == decTag) { // initial constructor
data.cut(-decTag.coding().length());
int len = ASNLib::decodeLength(data);
if (len != (int)data.length())
return;
}
}
decodeTcapToXml(elem,data,op,0,searchArgs);
}
void TcapToXml::decodeTcapToXml(XmlElement* elem, DataBlock& data, Operation* op, unsigned int index, bool searchArgs)
{
DDebug(&__plugin,DebugAll,"TcapToXml::decodeTcapToXml(elem=%s[%p],op=%s[%p], searchArgs=%s) [%p]",
elem->getTag().c_str(),elem,(op ? op->name.c_str() : ""),op,String::boolText(searchArgs),this);
if (!data.length() || !elem)
return;
if (op)
decodeOperation(op,elem,data,searchArgs);
else
decodeRaw(elem,data);
}
bool TcapToXml::decodeOperation(Operation* op, XmlElement* elem, DataBlock& data, bool searchArgs)
{
if (!(op && elem && m_app))
return false;
const Parameter* param = (searchArgs ? op->args : op->res);
AsnTag opTag = (searchArgs ? op->argTag : op->retTag);
int err = TcapXApplication::NoError;
while (param && !TelEngine::null(param->name)) {
AsnTag tag;
AsnTag::decode(tag,data);
if (!decodeParam(param,tag,data,elem,m_app->addEncoding(),err)) {
if (!param->isOptional)
err = TcapXApplication::DataMissing;
}
else if (opTag == s_noTag) // should be only one child
break;
param++;
}
if (data.length())
decodeRaw(elem,data);
return true;
}
/**
* XmlToTcap
*/
const TCAPMap XmlToTcap::s_tcapMap[] = {
{"c", false, ""},
{"transport.mtp.", true, ""},
{"transport.sccp.CallingPartyAddress.gt.encoding", false, "CallingPartyAddress.gt.encoding"},
{"transport.sccp.CallingPartyAddress.gt.plan", false, "CallingPartyAddress.gt.np"},
{"transport.sccp.CallingPartyAddress.gt.nature", false, "CallingPartyAddress.gt.nai"},
{"transport.sccp.CallingPartyAddress.gt.translation", false, "CallingPartyAddress.gt.tt"},
{"transport.sccp.CallingPartyAddress.", true, "CallingPartyAddress"},
{"transport.sccp.CalledPartyAddress.gt.encoding", false, "CalledPartyAddress.gt.encoding"},
{"transport.sccp.CalledPartyAddress.gt.plan", false, "CalledPartyAddress.gt.np"},
{"transport.sccp.CalledPartyAddress.gt.nature", false, "CalledPartyAddress.gt.nai"},
{"transport.sccp.CalledPartyAddress.gt.translation", false, "CalledPartyAddress.gt.tt"},
{"transport.sccp.CalledPartyAddress.", true, "CalledPartyAddress"},
{"transport.tcap.request-type", false, "tcap.request.type"},
{"transport.tcap.abort-cause", false, "tcap.transaction.abort.cause"},
{"transport.tcap.abort-information", false, "tcap.transaction.abort.information"},
{"transport.tcap.dialog.type", false, "tcap.dialogPDU.dialog-pdu-type"},
{"transport.tcap.dialog.userInformation", true, "tcap.dialogPDU.userInformation"},
{"transport.tcap.dialog.", false, "tcap.dialogPDU"},
{"transport.tcap.", true, "tcap.transaction"},
{"application", false, "tcap.dialogPDU.application-context-name"},
{0, ""},
};
XmlToTcap::XmlToTcap(TcapXApplication* app)
: Mutex(false,"XmlToTcap"),
m_app(app), m_frag(0), m_decl(0), m_elem(0)
{
DDebug(&__plugin,DebugAll,"XmlToTcap created for application=%s[%p] [%p]",m_app->toString().c_str(),m_app,this);
}
XmlToTcap::~XmlToTcap()
{
DDebug(&__plugin,DebugAll,"XmlToTcap destroyed [%p]",this);
reset();
}
void XmlToTcap::reset()
{
DDebug(&__plugin,DebugAll,"XmlToTcap::reset() m_elem = %s[%p], m_decl=%p",(m_elem ? m_elem->tag() : ""),m_elem,m_decl);
TelEngine::destruct(m_decl);
TelEngine::destruct(m_elem);
m_type = Unknown;
}
const TCAPMap* XmlToTcap::findMap(String& path)
{
XDebug(&__plugin,DebugAll,"XmlToTcap::findMap(%s) [%p]",path.c_str(),this);
const TCAPMap* map = s_tcapMap;
while (map && map->path) {
if (path == map->path || path.startsWith(map->path))
return map;
map++;
}
return 0;
}
bool XmlToTcap::validDeclaration()
{
Lock l(this);
if (!m_decl)
return false;
DDebug(&__plugin,DebugAll,"XmlToTcap::validDeclaration() [%p]",this);
const NamedList& decl = m_decl->getDec();
NamedString* vers = decl.getParam(YSTRING("version"));
NamedString* enc = decl.getParam(YSTRING("encoding"));
if (TelEngine::null(vers) || (*vers != "1.0") || TelEngine::null(enc) || (*enc != "UTF-8"))
return false;
return true;
}
bool XmlToTcap::checkXmlns()
{
Lock l(this);
if (!m_elem)
return false;
String* xmlns = m_elem->xmlns();
if (TelEngine::null(xmlns)) {
if (m_app->state() == TcapXApplication::Waiting)
return false;
}
else {
if (s_namespace != *xmlns)
return false;
}
return true;
}
bool XmlToTcap::valid()
{
Lock l(this);
if (!m_frag)
return false;
DDebug(&__plugin,DebugAll,"XmlToTcap::valid() [%p]",this);
while (XmlChild* child = m_frag->pop()) {
if (XmlDeclaration* decl = child->xmlDeclaration()) {
if (!m_decl)
m_decl = decl;
else
return false;
}
else if (XmlElement* elem = child->xmlElement()) {
if (!m_elem) {
if (s_msgTag != elem->tag()) {
Debug(&__plugin,DebugInfo,"XmlToTcap::valid() - missing root tag %s [%p]",s_msgTag.c_str(),this);
return false;
}
m_elem = elem;
break;
}
else
return false;
}
else
TelEngine::destruct(child);
}
return true;
}
void XmlToTcap::setXmlFragment(XmlFragment* frag)
{
Lock l(this);
reset();
m_frag = frag;
}
void XmlToTcap::encodeOperation(Operation* op, XmlElement* elem, DataBlock& payload, int& err, bool searchArgs)
{
if (!(op && elem))
return;
const Parameter* param = (searchArgs ? op->args : op->res);
AsnTag opTag = (searchArgs ? op->argTag : op->retTag);
while (param && !TelEngine::null(param->name)) {
DataBlock db;
if (!encodeParam(param,db,elem,err)) {
if (!param->isOptional)
err = TcapXApplication::DataMissing;
}
else {
payload.append(db);
if (opTag == s_noTag)
break;
}
param++;
}
XmlElement* child = elem->pop();
while (child) {
DataBlock db;
encodeRaw(param,db,child,err);
payload.append(db);
TelEngine::destruct(child);
child = elem->pop();
}
return;
}
bool XmlToTcap::encodeComponent(DataBlock& payload, XmlElement* elem, bool searchArgs, int& err, Operation* op)
{
DDebug(&__plugin,DebugAll,"XmlToTcap::encodeComponent(elem=%p) [%p]",elem,this);
if (!elem)
return false;
if (op)
encodeOperation(op,elem,payload,err,searchArgs);
else
encodeRaw(0,payload,elem,err);
if (elem->getTag() == s_component) {
AsnTag tag = ( op ? (searchArgs ? op->argTag : op->retTag) : s_sequenceTag);
if (tag != s_noTag) {
payload.insert(ASNLib::buildLength(payload));
payload.insert(tag.coding());
}
}
return true;
}
bool XmlToTcap::handleComponent(NamedList& tcapParams, XmlElement* elem)
{
DDebug(&__plugin,DebugAll,"XMLToTcap::handleComponent(params=%p, elem=%p) [%p]",&tcapParams,elem,this);
if (!elem && elem->getTag() == s_component)
return false;
unsigned int index = tcapParams.getIntValue(s_tcapCompCount) + 1;
String prefix = s_tcapCompPrefix;
prefix << "." << index;
Operation* op = 0;
int type = 0;
const NamedList& comp = elem->attributes();
for (unsigned int i = 0; i < comp.count(); i++) {
NamedString* ns = comp.getParam(i);
if (TelEngine::null(ns))
continue;
if (ns->name() == s_typeStr) {
tcapParams.setParam(prefix + "." + s_tcapCompType,*ns);
type = SS7TCAP::lookupComponent(*ns);
}
else if (ns->name() == s_tcapOpCode) {
op = (Operation*)findOperation(m_app->type(),*ns);
if (!op)
continue;
tcapParams.setParam(prefix + "." + s_tcapOpCode,String(op->code));
tcapParams.setParam(prefix + "." + s_tcapOpCodeType,(op->local ? "local" : "global"));
}
else if (ns->name() == s_tcapErrCode) {
op = (Operation*)findError(m_app->type(),*ns);
if (!op)
continue;
tcapParams.setParam(prefix + "." + s_tcapErrCode,String(op->code));
tcapParams.setParam(prefix + "." + s_tcapErrCodeType,(op->local ? "local" : "global"));
}
else if (ns->name() == s_tcapProblemCode)
tcapParams.setParam(prefix + "." + s_tcapProblemCode,String(lookup(*ns,SS7TCAPError::s_errorTypes)));
else
tcapParams.setParam(prefix + "." + ns->name(),*ns);
}
DataBlock payload;
bool searchArgs = (type == SS7TCAP::TC_Invoke || type == SS7TCAP::TC_U_Error ? true : false);
int err = TcapXApplication::NoError;
if (!encodeComponent(payload,elem,searchArgs,err,op))
return false;
String str;
str.hexify(payload.data(),payload.length(),' ');
tcapParams.setParam(prefix,str);
tcapParams.setParam(s_tcapCompCount,String(index));
return true;
}
bool XmlToTcap::parse(NamedList& tcapParams)
{
Lock l(this);
XDebug(&__plugin,DebugAll,"XmlToTcap::parse()");
tcapParams.setParam(s_tcapCompCount,String(0));
bool ok = parse(tcapParams,m_elem,"");
NamedString* c = tcapParams.getParam(s_capabTag);
if (!c) {
c = tcapParams.getParam(s_tcapReqType);
if (c) {
m_type = Tcap;
AppCtxt* appCtxt = 0;
NamedString* ctxt = tcapParams.getParam(s_tcapAppCtxt);
if (!TelEngine::null(ctxt))
appCtxt = (AppCtxt*)findCtxtFromStr(m_app->type(),*ctxt);
if (appCtxt)
tcapParams.setParam(s_tcapAppCtxt,appCtxt->oid);
// we shoudn't receive P_Abort from application, but make sure anyway
ctxt = tcapParams.getParam(s_tcapAbortCause);
if (!TelEngine::null(ctxt) && (*ctxt) == "pAbort") {
ctxt = tcapParams.getParam(s_tcapAbortInfo);
int code = lookup(*ctxt,SS7TCAPError::s_errorTypes);
*ctxt = String(code);
}
}
}
else
m_type = Capability;
return ok;
}
bool XmlToTcap::parse(NamedList& tcapParams, XmlElement* elem, String prefix)
{
XDebug(&__plugin,DebugAll,"XmlToTcap::parse(elem=%p, prefix=%s) [%p]",elem,prefix.c_str(),this);
if (!elem)
return true;
bool status = true;
bool hasChildren = false;
while (XmlElement* child = elem->pop()) {
hasChildren = true;
if (child->getTag() == s_component)
status = handleComponent(tcapParams,child);
else
status = parse(tcapParams,child, (!TelEngine::null(prefix) ? prefix + "." + child->getTag() : child->getTag()));
TelEngine::destruct(child);
if (!status)
break;
}
const NamedList& attrs = elem->attributes();
for (unsigned int i = 0; i < attrs.count(); i++) {
NamedString* ns = attrs.getParam(i);
if (TelEngine::null(ns))
continue;
String find = (!TelEngine::null(prefix) ? prefix + "." + ns->name() : ns->name());
const TCAPMap* map = findMap(find);
if (map) {
if (!TelEngine::null(map->name))
tcapParams.addParam(map->name,*ns);
else
tcapParams.addParam(ns->name(),elem->getText());
}
}
if (!hasChildren) {
const TCAPMap* map = findMap(prefix);
if (map) {
if (map->isPrefix) {
if (!TelEngine::null(map->name))
tcapParams.addParam(map->name + "." + elem->getTag(),elem->getText());
else
tcapParams.addParam(elem->getTag(),elem->getText());
}
else {
if (!TelEngine::null(map->name))
tcapParams.addParam(map->name,elem->getText());
else
tcapParams.addParam(elem->getTag(),elem->getText());
}
}
}
return status;
}
/**
* TcapXApplication
*/
TcapXApplication::TcapXApplication(const char* name, Socket* skt, TcapXUser* user)
: Mutex(true,name),
m_io(0), m_name(name), m_user(user),
m_sentXml(0), m_receivedXml(0),
m_sentTcap(0), m_receivedTcap(0),
m_state(Waiting),
m_tcap2Xml(this),
m_xml2Tcap(this)
{
if (skt) {
m_io = new XMLConnection(skt,this);
if (!m_io->startup()) {
delete m_io;
m_io = 0;
}
}
m_type = user->type();
Debug(&__plugin,DebugAll,"TcapXApplication created with name=%s and connection=%p [%p]",m_name.c_str(),m_io,this);
}
TcapXApplication::~TcapXApplication()
{
Debug(&__plugin,DebugAll,"TcapXApplication with name=%s destroyed [%p]",m_name.c_str(),this);
closeConnection();
while (m_io)
Thread::idle();
m_user = 0;
}
bool TcapXApplication::hasCapability(const char* cap)
{
if (!cap)
return false;
DDebug(&__plugin,DebugAll,"TcapXApplication::hasCapability(cap=%s) [%p]",cap,this);
Lock l(this);
ObjList* o = m_capab.find(cap);
if (!o)
return false;
String* str = static_cast<String*>(o->get());
if (!(str && (*str == cap)))
return false;
return true;
}
bool TcapXApplication::canHandle(NamedList& params)
{
DDebug(&__plugin,DebugAll,"TcapXApplication::canHandle(params=%p) [%p]",&params,this);
if (m_state != Active)
return false;
int compCount = params.getIntValue(s_tcapCompCount,0);
for (int i = 1; i <= compCount; i++) {
NamedString* opCode = params.getParam(s_tcapCompPrefixSep + String(i) + "." + s_tcapOpCode);
NamedString* opType = params.getParam(s_tcapCompPrefixSep + String(i) + "." + s_tcapOpCodeType);
if (TelEngine::null(opCode) || TelEngine::null(opType))
continue;
const Operation* op = findOperation(m_type,opCode->toInteger(),(*opType == "local" ? true : false));
if (!op)
continue;
const Capability* cap = findCapability(m_type,op->name);
if (!cap)
continue;
if (!hasCapability(cap->name))
return false;
}
return true;
}
void TcapXApplication::closeConnection()
{
DDebug(&__plugin,DebugAll,"TcapXApplication::closeConnection() - app=%s closing [%p]",m_name.c_str(),this);
Lock l(this);
if (m_io)
m_io->cancel();
l.drop();
}
void TcapXApplication::setIO(XMLConnection* io)
{
DDebug(&__plugin,DebugAll,"TcapXApplication::setIO(io=%p) - app=%s[%p]",io,m_name.c_str(),this);
Lock l(this);
m_io = io;
if (!m_io && m_user)
m_user->removeApp(this);
}
bool TcapXApplication::supportCapability(const String& capab)
{
if (!findDefCapability(m_type,capab))
return false;
return true;
}
bool TcapXApplication::handleXML()
{
Debug(&__plugin,DebugAll,"TcapXApplication::handleXML() - %s[%p]",m_name.c_str(),this);
if (!m_xml2Tcap.checkXmlns()) {
Debug(&__plugin,DebugInfo,"TcapXApplication=%s - XMLNS mismatch, closing the connection [%p]",m_name.c_str(),this);
closeConnection();
return false;
}
NamedList params("xml");
if (!m_xml2Tcap.parse(params)) {
Debug(&__plugin,DebugInfo,"TcapXApplication=%s - parse error, closing the connection [%p]",m_name.c_str(),this);
closeConnection();
return false;
};
if (m_user->printMessages()) {
String tmp;
params.dump(tmp,"\r\n ",'\'',true);
Debug(&__plugin,DebugAll,"App=%s[%p] parsed params %s from xml",m_name.c_str(),this,tmp.c_str());
}
switch (m_xml2Tcap.type()) {
case XmlToTcap::Capability:
return handleCapability(params);
case XmlToTcap::Tcap:
return handleTcap(params);
case XmlToTcap::Unknown:
default:
Debug(&__plugin,DebugInfo,"TcapXApplication=%s - unknown XML message [%p]",m_name.c_str(),this);
closeConnection();
return false;
}
return true;
}
bool TcapXApplication::sendTcapMsg(NamedList& params)
{
DDebug(&__plugin,DebugAll,"TcapXApplication::sentTcapMsg(params=%p) [%p]",&params,this);
XmlFragment* msg = new XmlFragment();
bool ok = m_tcap2Xml.buildXMLMessage(params,msg,TcapToXml::Tcap);
if (m_user->printMessages()) {
String tmp;
msg->toString(tmp,false,"\r\n"," ",false);
Debug(&__plugin,DebugInfo,"App=%s[%p] is sending XML \n%s",m_name.c_str(),this,tmp.c_str());
}
if (ok && m_io) {
m_io->writeData(msg);
m_sentXml++;
}
delete msg;
return ok;
}
bool TcapXApplication::handleCapability(NamedList& params)
{
DDebug(&__plugin,DebugAll,"TcapXApplication::handleCapability() - app=%s [%p]",m_name.c_str(),this);
Lock l(this);
bool firstCap = true;
for (unsigned int i = 0; i < params.count(); i++) {
NamedString* ns = params.getParam(i);
if (!ns)
continue;
if (ns->name() == s_capabTag) {
if (TelEngine::null(ns)) {
m_capab.clear();
reportState(ShutDown);
return true;
}
else {
if (!supportCapability(*ns)) {
reportState(Inactive,String("Unsupported: ") + *ns);
return false;
}
if (firstCap && m_state == Active) {
m_capab.clear();
firstCap = false;
}
m_capab.append(new String(*ns));
}
}
}
if (m_state == Waiting)
reportState(Active);
return true;
}
bool TcapXApplication::handleIndication(NamedList& tcap)
{
DDebug(&__plugin,DebugAll,"TcapXApplication::handleIndication() - app=%s state=%s [%p]",m_name.c_str(),lookup(m_state,s_appStates),this);
if (m_user->printMessages()) {
String tmp;
tcap.dump(tmp,"\r\n ",'\'',true);
Debug(&__plugin,DebugInfo,"App=%s[%p] received TCAP indication %s",m_name.c_str(),this,tmp.c_str());
}
int dialog = SS7TCAP::lookupTransaction(tcap.getValue(s_tcapReqType));
String ltid = tcap.getValue(s_tcapLocalTID);
NamedString* rtid = tcap.getParam(s_tcapRemoteTID);
bool saveID = false, removeID = false;
String appID;
switch (dialog) {
case SS7TCAP::TC_Unidirectional:
if (state() != Active)
return false;
tcap.setParam(s_tcapLocalTID,"");
break;
case SS7TCAP::TC_Begin:
case SS7TCAP::TC_QueryWithPerm:
case SS7TCAP::TC_QueryWithoutPerm:
if (state() != Active || TelEngine::null(rtid))
return false;
tcap.setParam(s_tcapLocalTID,"");
saveID = true;
break;
case SS7TCAP::TC_Continue:
case SS7TCAP::TC_ConversationWithPerm:
case SS7TCAP::TC_ConversationWithoutPerm:
case SS7TCAP::TC_Notice:
case SS7TCAP::TC_Unknown:
if (TelEngine::null(ltid))
return false;
lock();
appID = m_ids.findAppID(ltid);
if (TelEngine::null(appID)) {
appID = m_pending.findTcapID(*rtid);
if (TelEngine::null(appID)) {
unlock();
reportError("Unknown request ID");
return false;
}
m_pending.remove(appID);
}
unlock();
break;
case SS7TCAP::TC_End:
case SS7TCAP::TC_Response:
case SS7TCAP::TC_U_Abort:
case SS7TCAP::TC_P_Abort:
if (TelEngine::null(ltid))
return false;
lock();
appID = m_ids.findAppID(ltid);
if (TelEngine::null(appID)) {
appID = m_pending.findTcapID(ltid);
if (TelEngine::null(appID)) {
unlock();
reportError("Unknown request ID");
return false;
}
m_pending.remove(appID);
}
unlock();
removeID = true;
break;
default:
return false;
}
tcap.setParam(s_tcapLocalTID,appID);
bool ok = sendTcapMsg(tcap);
Lock l(this);
if (saveID)
m_pending.appendID(ltid,*rtid);
if (removeID) {
m_ids.removeAppID(appID);
if (m_state == ShutDown && !trCount())
reportState(Inactive);
}
m_receivedTcap++;
return ok;
}
bool TcapXApplication::handleTcap(NamedList& tcap)
{
DDebug(&__plugin,DebugAll,"TcapXApplication::handleTcap() - app=%s state=%s [%p]",m_name.c_str(),lookup(m_state,s_appStates),this);
int dialog = SS7TCAP::lookupTransaction(tcap.getValue(s_tcapReqType));
String ltid = tcap.getValue(s_tcapLocalTID);
String rtid = tcap.getValue(s_tcapRemoteTID);
bool saveID = false;
bool removeID = false;
lock();
String tcapID = m_ids.findTcapID(ltid);
unlock();
switch (dialog) {
case SS7TCAP::TC_Unknown:
case SS7TCAP::TC_Unidirectional:
break;
case SS7TCAP::TC_Begin:
case SS7TCAP::TC_QueryWithPerm:
case SS7TCAP::TC_QueryWithoutPerm:
if (TelEngine::null(ltid)) {
reportError("Missing request ID");
return false;
}
if (!TelEngine::null(tcapID)) {
reportError("Duplicate request ID");
return false;
}
saveID = true;
break;
case SS7TCAP::TC_Continue:
case SS7TCAP::TC_ConversationWithPerm:
case SS7TCAP::TC_ConversationWithoutPerm:
if (TelEngine::null(ltid)) {
reportError("Missing request ID");
return false;
}
if (TelEngine::null(tcapID)) {
if (!TelEngine::null(rtid)) {
lock();
tcapID = m_pending.findTcapID(rtid);
unlock();
if (TelEngine::null(tcapID)) {
reportError("Unknown request ID");
return false;
}
lock();
m_pending.removeAppID(tcapID);
unlock();
saveID = true;
}
else {
reportError("Unknown request ID");
return false;
}
}
break;
case SS7TCAP::TC_End:
case SS7TCAP::TC_Response:
case SS7TCAP::TC_U_Abort:
if (TelEngine::null(ltid)) {
reportError("Missing request ID");
return false;
}
if (TelEngine::null(tcapID)) {
if (!TelEngine::null(rtid)) {
lock();
tcapID = m_pending.findTcapID(rtid);
unlock();
if (TelEngine::null(tcapID)) {
reportError("Unknown request ID");
return false;
}
lock();
m_pending.removeAppID(tcapID);
unlock();
}
else {
reportError("Unknown request ID");
return false;
}
}
removeID = true;
break;
case SS7TCAP::TC_P_Abort:
case SS7TCAP::TC_Notice:
default:
reportError("Invalid request");
return false;
}
if (!m_user)
return false;
tcap.setParam(s_tcapLocalTID,tcapID);
if (m_user->printMessages()) {
String tmp;
tcap.dump(tmp,"\r\n ",'\'',true);
Debug(&__plugin,DebugInfo,"App=%s[%p] is sending TCAP request %s",m_name.c_str(),this,tmp.c_str());
}
SS7TCAPError error = m_user->applicationRequest(this,tcap,dialog);
if (error.error() != SS7TCAPError::NoError) {
NamedString* err = tcap.getParam(s_tcapRequestError);
reportError(TelEngine::null(err) ? error.errorName() : *err);
return false;
}
Lock l(this);
if (removeID) {
m_ids.removeAppID(ltid);
if (m_state == ShutDown && !trCount())
reportState(Inactive);
}
if (saveID)
m_ids.appendID(tcap.getValue(s_tcapLocalTID),ltid);
m_sentTcap++;
return true;
}
void TcapXApplication::receivedXML(XmlFragment* frag)
{
Debug(&__plugin,DebugAll,"TcapXApplication::receivedXML(frag=%p) - %s[%p]",frag,m_name.c_str(),this);
if (!frag)
return;
if (m_user->printMessages()) {
String tmp;
frag->toString(tmp,false,"\r\n"," ",false);
Debug(&__plugin,DebugInfo,"App=%s[%p] received XML \n%s",m_name.c_str(),this,tmp.c_str());
}
m_xml2Tcap.setXmlFragment(frag);
if (!m_xml2Tcap.valid()) {
Debug(&__plugin,DebugInfo,"TcapXApplication=%s - invalid message, closing the connection [%p]",m_name.c_str(),this);
closeConnection();
return;
}
if (m_state == Waiting && !m_xml2Tcap.hasDeclaration()) {
Debug(&__plugin,DebugInfo,"TcapXApplication=%s - initial XML declaration missing, closing the connection [%p]",m_name.c_str(),this);
closeConnection();
return;
}
if (m_xml2Tcap.hasDeclaration() && !m_xml2Tcap.validDeclaration()) {
Debug(&__plugin,DebugInfo,"TcapXApplication=%s - XML declaration mismatch, closing the connection [%p]",m_name.c_str(),this);
closeConnection();
return;
}
if (handleXML())
m_receivedXml++;
}
void TcapXApplication::reportState(State state, const char* error)
{
DDebug(&__plugin,DebugAll,"TcapXApplication::reportState(state=%s, error=%s) [%p]",lookup(state,s_appStates),error,this);
m_state = state;
switch (m_state) {
case Waiting:
break;
case Active:
sendStateResponse();
break;
case ShutDown:
Debug(&__plugin,DebugInfo,"Requested shutdown, %d transactions pending [%p]",trCount(),this);
if (trCount())
break;
m_state = Inactive;
case Inactive:
sendStateResponse(error);
closeConnection();
default:
break;
}
}
void TcapXApplication::sendStateResponse(const char* error)
{
DDebug(&__plugin,DebugAll,"TcapXApplication::sendStateResponse(error=%s) [%p]",error,this);
NamedList params("xml");
params.setParam("state",lookup(m_state,s_appStates));
if (error)
params.setParam("error",error);
XmlFragment* msg = new XmlFragment();
bool ok = m_tcap2Xml.buildXMLMessage(params,msg,TcapToXml::State);
if (m_user->printMessages()) {
String tmp;
msg->toString(tmp,false,"\r\n"," ",false);
Debug(&__plugin,DebugInfo,"App=%s[%p] is sending XML \n%s",m_name.c_str(),this,tmp.c_str());
}
if (ok && m_io) {
m_io->writeData(msg);
m_sentXml++;
}
delete msg;
}
void TcapXApplication::reportError(const char* err)
{
if (!err)
return;
DDebug(&__plugin,DebugInfo,"TcapXApplication::reportError(error=%s) [%p]",err,this);
}
void TcapXApplication::status(NamedList& status)
{
DDebug(&__plugin,DebugInfo,"TcapXApplication::status() [%p]",this);
Lock l(this);
status.setParam("receivedXML",String(m_receivedXml));
status.setParam("sentXML",String(m_sentXml));
status.setParam("receivedTcap",String(m_receivedTcap));
status.setParam("sentTcap",String(m_sentTcap));
}
/**
* TcapXUser
*/
TcapXUser::TcapXUser(const char* name)
: TCAPUser(name),
Mutex(true,name),
m_appsMtx(true,"TCAPXApps"),
m_listener(0), m_type(MAP),
m_printMsg(false), m_addEnc(false)
{
Debug(&__plugin,DebugAll,"TcapXUser '%s' created [%p]",toString().c_str(),this);
}
TcapXUser::~TcapXUser()
{
Debug(&__plugin,DebugAll,"TcapXUser '%s' destroyed [%p]",toString().c_str(),this);
lock();
if (m_listener)
m_listener->cancel();
if (tcap())
attach(0);
unlock();
m_appsMtx.lock();
for (ObjList* o = m_apps.skipNull(); o; o = o->skipNext()) {
TcapXApplication* app = static_cast<TcapXApplication*>(o->get());
if (app)
app->closeConnection();
}
m_appsMtx.unlock();
while (m_listener)
Thread::idle();
}
bool TcapXUser::initialize(NamedList& sect)
{
Debug(this,DebugAll,"TcapXUser::initialize() [%p]",this);
Lock l(this);
if (!m_listener) {
m_listener = new XMLConnListener(this,sect);
if (!m_listener->init()) {
delete m_listener;
m_listener = 0;
return false;
}
}
m_type = (UserType)lookup(sect.getValue(s_typeStr,"MAP"),s_userTypes,m_type);
m_printMsg = sect.getBoolValue("print-messages",false);
m_addEnc = sect.getBoolValue("add-encoding",false);
if (!tcap() && !findTCAP(sect.getValue("tcap",0)))
return false;
return true;
}
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);
}
bool TcapXUser::tcapIndication(NamedList& params)
{
DDebug(this,DebugAll,"TcapXUser::tcapIndication() [%p]",this);
NamedString* ltid = params.getParam(s_tcapLocalTID);
if (TelEngine::null(ltid))
return false;
int dialog = SS7TCAP::lookupTransaction(params.getValue(s_tcapReqType));
ObjList* o = m_trIDs.find(*ltid);
NamedString* tcapID = 0;
if (o)
tcapID = static_cast<NamedString*>(o->get());
bool searchApp = false, removeID = false;
switch (dialog) {
case SS7TCAP::TC_Unidirectional:
return sendToApp(params);
case SS7TCAP::TC_Begin:
case SS7TCAP::TC_QueryWithPerm:
case SS7TCAP::TC_QueryWithoutPerm:
if (TelEngine::null(ltid) || !TelEngine::null(tcapID))
return false;
return sendToApp(params);
case SS7TCAP::TC_Continue:
case SS7TCAP::TC_ConversationWithPerm:
case SS7TCAP::TC_ConversationWithoutPerm:
if (TelEngine::null(ltid) || TelEngine::null(tcapID))
return false;
searchApp = true;
break;
case SS7TCAP::TC_End:
case SS7TCAP::TC_Response:
case SS7TCAP::TC_U_Abort:
case SS7TCAP::TC_P_Abort:
case SS7TCAP::TC_Notice:
case SS7TCAP::TC_Unknown:
if (TelEngine::null(ltid) || TelEngine::null(tcapID))
return false;
searchApp = true;
removeID = true;
break;
default:
return false;
}
Lock la(m_appsMtx);
o = m_apps.find(*tcapID);
if (!o && searchApp)
return false;
TcapXApplication* app = static_cast<TcapXApplication*>(o->get());
if (searchApp && !app)
return false;
if (removeID) {
reorderApps(app);
m_trIDs.remove(tcapID);
}
la.drop();
return sendToApp(params,app);
}
bool TcapXUser::sendToApp(NamedList& params, TcapXApplication* app)
{
DDebug(this,DebugAll,"TcapXUser::sendToApp(params=%p,app=%s[%p]) [%p]",&params,(app ? app->toString().c_str() : ""),app,this);
Lock l(m_appsMtx);
if (!app)
app = findApplication(params);
if (!app)
return false;
m_trIDs.append(new NamedString(params.getValue(s_tcapLocalTID),app->toString()));
return (app && app->handleIndication(params));
}
TcapXApplication* TcapXUser::findApplication(NamedList& params)
{
DDebug(this,DebugAll,"TcapXUser::findApplication() [%p]",this);
TcapXApplication* app = 0;
for (ObjList* o = m_apps.skipNull(); o; o = o->skipNext()) {
app = static_cast<TcapXApplication*>(o->get());
if (app->canHandle(params))
break;
}
// reorder list
reorderApps(app);
return app;
}
void TcapXUser::reorderApps(TcapXApplication* app)
{
if (!app)
return;
ObjList* appObj = m_apps.find(app);
if (!appObj)
return;
ObjList* next = appObj->next();
TcapXApplication* ins = 0;
while (next) {
TcapXApplication* nextApp = static_cast<TcapXApplication*>(next->get());
if (nextApp) {
if (app->trCount() + 1 > nextApp->trCount()) {
if (!ins) {
ins = app;
m_apps.remove(app,false);
}
next = next->next();
}
else {
if (ins) {
next->insert(app);
ins = 0;
}
break;
}
}
else
break;
}
if (ins)
m_apps.append(app);
}
void TcapXUser::statusString(String& str)
{
DDebug(this,DebugAll,"TcapXUser::statusString() [%p]",this);
Lock l(m_appsMtx);
NamedList params("");
for (ObjList* o = m_apps.skipNull(); o; o = o->skipNext()) {
TcapXApplication* app = static_cast<TcapXApplication*>(o->get());
if (!app)
continue;
str.append(app->toString(),",") << "=" << toString() << "|" << lookup(m_type,s_userTypes);
app->status(params);
str << "|" << params.getIntValue(YSTRING("receivedXML"));
str << "|" << params.getIntValue(YSTRING("sentXML"));
str << "|" << params.getIntValue(YSTRING("receivedTcap"));
str << "|" << params.getIntValue(YSTRING("sentTcap"));
}
}
bool TcapXUser::managementNotify(SCCP::Type type, NamedList& params)
{
// TODO
// check docs if they say anything about management
return true;
}
bool TcapXUser::findTCAP(const char* name)
{
if (!name)
return false;
SignallingComponent* tcap = 0;
SignallingEngine* engine = SignallingEngine::self(true);
if (engine)
tcap = engine->find(name,"SS7TCAPITU",tcap);
if (tcap) {
Debug(this,DebugAll,"TcapXUser '%s' attaching to TCAP=%s [%p]",toString().c_str(),name,this);
attach(YOBJECT(SS7TCAPITU,tcap));
}
return (tcap != 0);
}
bool TcapXUser::createApplication(Socket* skt, String& addr)
{
if (!skt)
return false;
String appName = toString() + ":" + addr;
Lock l(m_appsMtx);
// it's new, put it at the top of the list
m_apps.insert(new TcapXApplication(appName,skt,this));
return true;
}
int TcapXUser::managementState()
{
DDebug(this,DebugAll,"TcapXUser::managementState() - user=%s[%p]",toString().c_str(),this);
Lock l(m_appsMtx);
for (ObjList* o = m_apps.skipNull(); o; o = o->skipNext()) {
TcapXApplication* app = static_cast<TcapXApplication*>(o->get());
if (!app)
continue;
if (app->state() == TcapXApplication::Active)
return SCCPManagement::UserInService;
}
return SCCPManagement::UserOutOfService;
}
void TcapXUser::setListener(XMLConnListener* list)
{
Lock l(this);
m_listener = list;
}
SS7TCAPError TcapXUser::applicationRequest(TcapXApplication* app, NamedList& params, int reqType)
{
DDebug(this,DebugAll,"TcapXUser::applicationRequest() - user=%s, request from app=%s[%p] [%p]",
toString().c_str(),(app ? app->toString().c_str() : ""),app,this);
SS7TCAPError error((tcap() ? tcap()->tcapType() : SS7TCAP::ITUTCAP));
if (!app)
return error;
if (tcap()) {
params.setParam(s_tcapUser,toString());
error = tcap()->userRequest(params);
}
else {
params.setParam(s_tcapRequestError,"No TCAP attached");
error.setError(SS7TCAPError::Transact_UnassignedTransactionID);
return error;
}
bool saveID = false;
bool removeID = false;
switch (reqType) {
case SS7TCAP::TC_Begin:
case SS7TCAP::TC_QueryWithPerm:
case SS7TCAP::TC_QueryWithoutPerm:
saveID = true;
break;
case SS7TCAP::TC_End:
case SS7TCAP::TC_Response:
case SS7TCAP::TC_U_Abort:
removeID = true;
break;
case SS7TCAP::TC_P_Abort:
case SS7TCAP::TC_Notice:
case SS7TCAP::TC_Unknown:
case SS7TCAP::TC_Unidirectional:
case SS7TCAP::TC_Continue:
case SS7TCAP::TC_ConversationWithPerm:
case SS7TCAP::TC_ConversationWithoutPerm:
default:
break;
}
Lock la(m_appsMtx);
NamedString* ltid = params.getParam(s_tcapLocalTID);
if (saveID) {
reorderApps(app);
if (TelEngine::null(ltid)) {
params.setParam(s_tcapRequestError,"TCAP error");
error.setError(SS7TCAPError::Transact_UnassignedTransactionID);
}
else
m_trIDs.append(new NamedString(*ltid,app->toString()));
}
if (removeID) {
reorderApps(app);
if (TelEngine::null(ltid) ||!m_trIDs.find(*ltid))
error.setError(SS7TCAPError::Transact_UnassignedTransactionID);
else
m_trIDs.remove(*ltid);
}
return error;
}
/**
* TcapXModule
*/
TcapXModule::TcapXModule()
: Module("camel_map","misc"),
m_usersMtx(true,"TCAPXUsers")
{
Output("Loaded TCAPXML module");
}
TcapXModule::~TcapXModule()
{
Output("Unloaded module TCAPXML");
}
void TcapXModule::initialize()
{
Output("Initializing module TCAPXML");
Module::initialize();
Configuration cfg(Engine::configFile(name()));
cfg.load();
initUsers(cfg);
}
bool TcapXModule::unload()
{
if (!lock(500000))
return false;
uninstallRelays();
return true;
}
void TcapXModule::initUsers(Configuration& cfg)
{
DDebug(&__plugin,DebugAll,"TcapXModule::initUsers() [%p]",this);
int n = cfg.sections();
Lock l(m_usersMtx);
for (int i = 0; i < n; i++) {
NamedList* sect = cfg.getSection(i);
if (!sect)
continue;
String name(*sect);
if (name.startSkip("tcap") && name) {
if (!sect->getBoolValue("enable",true)) {
m_users.remove(name);
continue;
}
ObjList* o = m_users.find(name);
TcapXUser* usr = (o ? static_cast<TcapXUser*>(o->get()) : 0);
if (!usr) {
usr = new TcapXUser(name);
m_users.append(usr);
}
if (!usr->initialize(*sect)) {
Debug(&__plugin,DebugInfo,"TcapXModule::initUsers() - user '%s' failed to initialize [%p]",name.c_str(),this);
m_users.remove(name);
}
}
}
}
bool TcapXModule::received(Message& msg, int id)
{
return Module::received(msg,id);
}
unsigned int TcapXModule::applicationCount()
{
Lock l(m_usersMtx);
unsigned int count = 0;
for (ObjList* o = m_users.skipNull(); o; o = o->skipNext()) {
TcapXUser* user = static_cast<TcapXUser*>(o->get());
count += user->applicationCount();
}
return count;
}
void TcapXModule::statusModule(String& str)
{
Module::statusModule(str);
str.append("format=User|Type|ReceivedXML|SentXML|ReceivedTCAP|SentTcap",",");
}
void TcapXModule::statusParams(String& str)
{
str.append("count=",",") << applicationCount();
}
void TcapXModule::statusDetail(String& str)
{
Lock l(m_usersMtx);
for (ObjList* o = m_users.skipNull(); o; o = o->skipNext()) {
TcapXUser* user = static_cast<TcapXUser*>(o->get());
if (!user)
continue;
user->statusString(str);
}
}
}; // anonymous namespace
/* vi: set ts=8 sw=4 sts=4 noet: */