ISDN BRI support, most Andrei's (andrei@null.ro) work.
Fixes and new features throughout the signalling engine. git-svn-id: http://yate.null.ro/svn/yate/trunk@2505 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
1050299bf2
commit
05b717e0b9
|
@ -22,6 +22,8 @@
|
|||
; type: string: Specify the link type
|
||||
; Allowed values:
|
||||
; ss7-isup: SS7 ISDN User Part over synchronous (HDLC) interface(s)
|
||||
; isdn-bri-net: ISDN network side of a data link over basic rate HDLC interface(s)
|
||||
; isdn-bri-cpe: ISDN CPE (user) side of a data link over basic rate HDLC interface(s)
|
||||
; isdn-pri-net: ISDN network side of a data link over one or more primary HDLC interface(s)
|
||||
; isdn-pri-cpe: ISDN CPE (user) side of a data link over one or more primary HDLC interface(s)
|
||||
; isdn-pri-mon: ISDN monitor of one or more primary HDLC interface(s)
|
||||
|
|
|
@ -28,8 +28,8 @@
|
|||
|
||||
using namespace TelEngine;
|
||||
|
||||
SignallingDumper::SignallingDumper(Type type)
|
||||
: m_type(type), m_output(0)
|
||||
SignallingDumper::SignallingDumper(Type type, bool network)
|
||||
: m_type(type), m_network(network), m_output(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -87,10 +87,15 @@ bool SignallingDumper::dump(void* buf, unsigned int len, bool sent, int link)
|
|||
case Q921:
|
||||
case Hdlc:
|
||||
{
|
||||
// add LAPD pseudoheader
|
||||
// add LAPD pseudoheader - see wiretap/libpcap.c
|
||||
hdr2.assign(0,16);
|
||||
unsigned char* ptr2 = (unsigned char*)hdr2.data();
|
||||
ptr2[6] = sent ? 1 : 0;
|
||||
// packet type: outgoing 4, sniffed 3, incoming 0
|
||||
ptr2[0] = 0x00;
|
||||
ptr2[1] = sent ? 0x04 : 0x00;
|
||||
// address: are we the network side?
|
||||
ptr2[6] = m_network ? 1 : 0;
|
||||
// ETH_P_LAPD
|
||||
ptr2[14] = 0x00;
|
||||
ptr2[15] = 0x30;
|
||||
}
|
||||
|
@ -149,20 +154,20 @@ void SignallingDumper::head()
|
|||
|
||||
// Create a dumper from file
|
||||
SignallingDumper* SignallingDumper::create(DebugEnabler* dbg, const char* filename, Type type,
|
||||
bool create, bool append)
|
||||
bool network, bool create, bool append)
|
||||
{
|
||||
if (!filename)
|
||||
return 0;
|
||||
File* f = new File;
|
||||
if (f->openPath(filename,true,false,create,append,true))
|
||||
return SignallingDumper::create(f,type);
|
||||
return SignallingDumper::create(f,type,network);
|
||||
Debug(dbg,DebugWarn,"Failed to create dumper '%s'",filename);
|
||||
delete f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Create a dumper from stream
|
||||
SignallingDumper* SignallingDumper::create(Stream* stream, Type type, bool writeHeader)
|
||||
SignallingDumper* SignallingDumper::create(Stream* stream, Type type, bool network, bool writeHeader)
|
||||
{
|
||||
if (!stream)
|
||||
return 0;
|
||||
|
@ -170,7 +175,7 @@ SignallingDumper* SignallingDumper::create(Stream* stream, Type type, bool write
|
|||
delete stream;
|
||||
return 0;
|
||||
}
|
||||
SignallingDumper* dumper = new SignallingDumper(type);
|
||||
SignallingDumper* dumper = new SignallingDumper(type,network);
|
||||
dumper->setStream(stream,writeHeader);
|
||||
return dumper;
|
||||
}
|
||||
|
@ -195,7 +200,7 @@ bool SignallingDumpable::setDumper(const String& name, bool create, bool append)
|
|||
type = SignallingDumper::Raw;
|
||||
else if (name.endsWith(".hex") || name.endsWith(".txt"))
|
||||
type = SignallingDumper::Hexa;
|
||||
SignallingDumper* dumper = SignallingDumper::create(0,name,type,create,append);
|
||||
SignallingDumper* dumper = SignallingDumper::create(0,name,type,m_dumpNet,create,append);
|
||||
if (dumper)
|
||||
setDumper(dumper);
|
||||
else
|
||||
|
|
|
@ -100,6 +100,13 @@ void* SignallingFactory::build(const String& type, const NamedList* name)
|
|||
}
|
||||
|
||||
|
||||
SignallingComponent::SignallingComponent(const char* name)
|
||||
: m_engine(0)
|
||||
{
|
||||
DDebug(engine(),DebugAll,"Component '%s' created [%p]",name,this);
|
||||
setName(name);
|
||||
}
|
||||
|
||||
void SignallingComponent::setName(const char* name)
|
||||
{
|
||||
debugName(0);
|
||||
|
@ -127,6 +134,16 @@ bool SignallingComponent::control(NamedList& params)
|
|||
return false;
|
||||
}
|
||||
|
||||
void SignallingComponent::engine(SignallingEngine* eng)
|
||||
{
|
||||
if (eng == m_engine)
|
||||
return;
|
||||
if (eng)
|
||||
eng->insert(this);
|
||||
else
|
||||
detach();
|
||||
}
|
||||
|
||||
void SignallingComponent::insert(SignallingComponent* component)
|
||||
{
|
||||
if (!component)
|
||||
|
@ -395,7 +412,7 @@ static TokenDict s_dict_causeCCITT[] = {
|
|||
{"noanswer", 0x13}, // No answer from user (user alerted)
|
||||
{"rejected", 0x15}, // Call Rejected
|
||||
{"moved", 0x16}, // Number changed
|
||||
{"non-sel-user-clearing", 0x1a}, // Non-selected user clearing
|
||||
{"answered", 0x1a}, // Non-selected user clearing (answered elsewhere)
|
||||
{"offline", 0x1b}, // Destination out of order
|
||||
{"invalid-number", 0x1c}, // Invalid number format
|
||||
{"facility-rejected", 0x1d}, // Facility rejected
|
||||
|
|
|
@ -99,6 +99,14 @@ bool SignallingInterface::notify(Notification event)
|
|||
}
|
||||
|
||||
|
||||
YCLASSIMP(SignallingReceiver,SignallingComponent)
|
||||
|
||||
SignallingReceiver::SignallingReceiver(const char* name)
|
||||
: SignallingComponent(name),
|
||||
m_ifaceMutex(true), m_interface(0)
|
||||
{
|
||||
}
|
||||
|
||||
SignallingReceiver::~SignallingReceiver()
|
||||
{
|
||||
if (m_interface)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -209,8 +209,9 @@ SignallingEvent* SignallingCallControl::getEvent(const Time& when)
|
|||
// Clear call list
|
||||
void SignallingCallControl::clearCalls()
|
||||
{
|
||||
Lock lock(this);
|
||||
lock();
|
||||
m_calls.clear();
|
||||
unlock();
|
||||
}
|
||||
|
||||
// Remove a call from list
|
||||
|
@ -218,11 +219,12 @@ void SignallingCallControl::removeCall(SignallingCall* call, bool del)
|
|||
{
|
||||
if (!call)
|
||||
return;
|
||||
Lock lock(this);
|
||||
lock();
|
||||
if (m_calls.remove(call,del))
|
||||
DDebug(DebugAll,
|
||||
"SignallingCallControl. Call (%p) removed from queue. Deleted: %s [%p]",
|
||||
call,String::boolText(del),this);
|
||||
"SignallingCallControl. Call (%p) removed%s from queue [%p]",
|
||||
call,(del ? " and deleted" : ""),this);
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
||||
|
@ -242,9 +244,11 @@ SignallingCall::SignallingCall(SignallingCallControl* controller, bool outgoing,
|
|||
|
||||
SignallingCall::~SignallingCall()
|
||||
{
|
||||
m_callMutex.lock();
|
||||
m_inMsg.clear();
|
||||
if (m_controller)
|
||||
m_controller->removeCall(this,false);
|
||||
m_callMutex.unlock();
|
||||
}
|
||||
|
||||
// Event termination notification
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -202,18 +202,29 @@ class SigLink : public RefObject
|
|||
{
|
||||
friend class SigLinkThread; // The thread must set m_thread to 0 on terminate
|
||||
public:
|
||||
enum Mask {
|
||||
MaskSS7 = 0x01,
|
||||
MaskIsdn = 0x02,
|
||||
MaskMon = 0x04,
|
||||
MaskNet = 0x10,
|
||||
MaskCpe = 0x20,
|
||||
MaskPri = 0x40,
|
||||
MaskBri = 0x80,
|
||||
};
|
||||
enum Type {
|
||||
SS7Isup,
|
||||
IsdnPriNet,
|
||||
IsdnPriCpe,
|
||||
IsdnPriMon,
|
||||
Unknown
|
||||
Unknown = 0,
|
||||
SS7Isup = MaskSS7,
|
||||
IsdnPriNet = MaskIsdn | MaskNet | MaskPri,
|
||||
IsdnBriNet = MaskIsdn | MaskNet | MaskBri,
|
||||
IsdnPriCpe = MaskIsdn | MaskCpe | MaskPri,
|
||||
IsdnBriCpe = MaskIsdn | MaskCpe | MaskBri,
|
||||
IsdnPriMon = MaskIsdn | MaskMon,
|
||||
};
|
||||
// Set link name and type. Append to plugin list
|
||||
SigLink(const char* name, Type type);
|
||||
// Cancel thread. Cleanup. Remove from plugin list
|
||||
virtual ~SigLink();
|
||||
inline int type() const
|
||||
inline Type type() const
|
||||
{ return m_type; }
|
||||
inline SignallingCallControl* controller() const
|
||||
{ return m_controller; }
|
||||
|
@ -266,7 +277,7 @@ protected:
|
|||
bool m_init; // True if already initialized
|
||||
bool m_inband; // True to send in-band tones through this link
|
||||
private:
|
||||
int m_type; // Link type
|
||||
Type m_type; // Link type
|
||||
String m_name; // Link name
|
||||
SigLinkThread* m_thread; // Event thread for call controller
|
||||
};
|
||||
|
@ -304,7 +315,7 @@ private:
|
|||
class SigIsdn : public SigLink
|
||||
{
|
||||
public:
|
||||
SigIsdn(const char* name, bool net);
|
||||
SigIsdn(const char* name, Type type);
|
||||
virtual ~SigIsdn();
|
||||
protected:
|
||||
virtual bool create(NamedList& params, String& error);
|
||||
|
@ -314,7 +325,7 @@ protected:
|
|||
inline ISDNQ931* q931()
|
||||
{ return static_cast<ISDNQ931*>(m_controller); }
|
||||
private:
|
||||
ISDNQ921* m_q921;
|
||||
ISDNLayer2* m_q921;
|
||||
SignallingInterface* m_iface;
|
||||
SigCircuitGroup* m_group;
|
||||
};
|
||||
|
@ -1263,8 +1274,10 @@ void SigDriver::handleEvent(SignallingEvent* event)
|
|||
// Route the call
|
||||
Message* m = ch->message("call.preroute",false,true);
|
||||
// Parameters to be copied to call.preroute
|
||||
static String params = "caller,called,callername,format,formats,callernumtype,callernumplan,callerpres,callerscreening,callednumtype,callednumplan,inn";
|
||||
static String params = "caller,called,callername,format,formats,callernumtype,callernumplan,callerpres,callerscreening,callednumtype,callednumplan,inn,overlapped";
|
||||
copySigMsgParams(*m,event,¶ms);
|
||||
if (m->getBoolValue("overlapped") && !m->getValue("called"))
|
||||
m->setParam("called","off-hook");
|
||||
// TODO: Add call control parameter ?
|
||||
if (!ch->startRouter(m)) {
|
||||
ch->hangup("temporary-failure");
|
||||
|
@ -1640,8 +1653,10 @@ void SigDriver::initialize()
|
|||
link = new SigSS7Isup(*sect);
|
||||
break;
|
||||
case SigLink::IsdnPriNet:
|
||||
case SigLink::IsdnBriNet:
|
||||
case SigLink::IsdnPriCpe:
|
||||
link = new SigIsdn(*sect,type == SigLink::IsdnPriNet);
|
||||
case SigLink::IsdnBriCpe:
|
||||
link = new SigIsdn(*sect,(SigLink::Type)type);
|
||||
break;
|
||||
case SigLink::IsdnPriMon:
|
||||
link = new SigIsdnMonitor(*sect);
|
||||
|
@ -1675,7 +1690,9 @@ void* SigParams::getObject(const String& name) const
|
|||
TokenDict SigLink::s_type[] = {
|
||||
{"ss7-isup", SS7Isup},
|
||||
{"isdn-pri-net", IsdnPriNet},
|
||||
{"isdn-bri-net", IsdnBriNet},
|
||||
{"isdn-pri-cpe", IsdnPriCpe},
|
||||
{"isdn-bri-cpe", IsdnBriCpe},
|
||||
{"isdn-pri-mon", IsdnPriMon},
|
||||
{0,0}
|
||||
};
|
||||
|
@ -1736,7 +1753,9 @@ bool SigLink::initialize(NamedList& params)
|
|||
minRxUnder = 25;
|
||||
break;
|
||||
case SigLink::IsdnPriNet:
|
||||
case SigLink::IsdnBriNet:
|
||||
case SigLink::IsdnPriCpe:
|
||||
case SigLink::IsdnBriCpe:
|
||||
minRxUnder = 2500;
|
||||
break;
|
||||
case SigLink::IsdnPriMon:
|
||||
|
@ -2168,8 +2187,8 @@ unsigned int SigSS7Isup::setPointCode(const NamedList& sect)
|
|||
/**
|
||||
* SigIsdn
|
||||
*/
|
||||
SigIsdn::SigIsdn(const char* name, bool net)
|
||||
: SigLink(name,net ? IsdnPriNet : IsdnPriCpe),
|
||||
SigIsdn::SigIsdn(const char* name, Type type)
|
||||
: SigLink(name,type),
|
||||
m_q921(0),
|
||||
m_iface(0),
|
||||
m_group(0)
|
||||
|
@ -2200,12 +2219,26 @@ bool SigIsdn::create(NamedList& params, String& error)
|
|||
return false;
|
||||
|
||||
// Q921
|
||||
buildName(compName,"Q921");
|
||||
params.setParam("debugname",compName);
|
||||
params.setParam("network",String::boolText(IsdnPriNet == type()));
|
||||
params.setParam("network",String::boolText(0 != (MaskNet & type())));
|
||||
params.setParam("print-frames",params.getValue("print-layer2PDU"));
|
||||
m_q921 = new ISDNQ921(params,compName);
|
||||
plugin.engine()->insert(m_q921);
|
||||
switch (type()) {
|
||||
case IsdnBriNet:
|
||||
buildName(compName,"Q921Management");
|
||||
params.setParam("debugname",compName);
|
||||
m_q921 = new ISDNQ921Management(params,compName,true);
|
||||
break;
|
||||
case IsdnBriCpe:
|
||||
buildName(compName,"Q921Management");
|
||||
params.setParam("debugname",compName);
|
||||
m_q921 = new ISDNQ921Management(params,compName,false);
|
||||
break;
|
||||
default:
|
||||
buildName(compName,"Q921");
|
||||
params.setParam("debugname",compName);
|
||||
m_q921 = new ISDNQ921(params,compName);
|
||||
break;
|
||||
}
|
||||
m_q921->engine(plugin.engine());
|
||||
|
||||
// Q931
|
||||
buildName(compName,"Q931");
|
||||
|
@ -2215,12 +2248,15 @@ bool SigIsdn::create(NamedList& params, String& error)
|
|||
plugin.engine()->insert(q931());
|
||||
|
||||
// Create links between components and enable them
|
||||
m_q921->SignallingReceiver::attach(m_iface);
|
||||
SignallingReceiver* recv = YOBJECT(SignallingReceiver,m_q921);
|
||||
if (recv)
|
||||
recv->attach(m_iface);
|
||||
m_iface->control(SignallingInterface::Enable);
|
||||
controller()->attach(m_group);
|
||||
m_q921->ISDNLayer2::attach(q931());
|
||||
m_q921->attach(q931());
|
||||
q931()->attach(m_q921);
|
||||
m_q921->multipleFrame(true,false);
|
||||
if (0 == (MaskBri & type()))
|
||||
m_q921->multipleFrame(0,true,false);
|
||||
|
||||
// Start thread
|
||||
if (!startThread(error,plugin.engine()->tickDefault()))
|
||||
|
@ -2234,9 +2270,11 @@ bool SigIsdn::reload(NamedList& params)
|
|||
if (q931())
|
||||
q931()->setDebug(params.getBoolValue("print-layer3PDU",false),
|
||||
params.getBoolValue("extended-debug",false));
|
||||
#if 0
|
||||
if (m_q921)
|
||||
m_q921->setDebug(params.getBoolValue("print-layer2PDU",false),
|
||||
params.getBoolValue("extended-debug",false));
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue