2f23277a38
git-svn-id: http://yate.null.ro/svn/yate/trunk@2815 acf43c95-373e-0410-b603-e72c3f656dc1
8794 lines
298 KiB
C++
8794 lines
298 KiB
C++
/*
|
|
* yatesig.h
|
|
* This file is part of the YATE Project http://YATE.null.ro
|
|
*
|
|
* Yet Another Signalling Stack - implements the support for SS7, ISDN and PSTN
|
|
*
|
|
* Yet Another Telephony Engine - a fully featured software PBX and IVR
|
|
* Copyright (C) 2004-2006 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.
|
|
*/
|
|
|
|
#ifndef __YATESIG_H
|
|
#define __YATESIG_H
|
|
|
|
#include <yateclass.h>
|
|
|
|
#ifdef _WINDOWS
|
|
|
|
#ifdef LIBYSIG_EXPORTS
|
|
#define YSIG_API __declspec(dllexport)
|
|
#else
|
|
#ifndef LIBYSIG_STATIC
|
|
#define YSIG_API __declspec(dllimport)
|
|
#endif
|
|
#endif
|
|
|
|
#endif /* _WINDOWS */
|
|
|
|
#ifndef YSIG_API
|
|
#define YSIG_API
|
|
#endif
|
|
|
|
/**
|
|
* Holds all Telephony Engine related classes.
|
|
*/
|
|
namespace TelEngine {
|
|
|
|
// Signalling classes
|
|
class SignallingDumper; // A generic data dumper
|
|
class SignallingDumpable; // A component that can dump data
|
|
class SignallingTimer; // A signalling timer
|
|
class SignallingCounter; // A signalling counter
|
|
class SignallingFactory; // A signalling component factory
|
|
class SignallingComponent; // Abstract signalling component that can be managed by the engine
|
|
class SignallingEngine; // Main signalling component holder
|
|
class SignallingThreadPrivate; // Engine private thread
|
|
class SignallingMessage; // Abstract signalling message
|
|
class SignallingCallControl; // Abstract phone call signalling
|
|
class SignallingCall; // Abstract single phone call
|
|
class SignallingEvent; // A single signalling related event
|
|
class SignallingCircuitEvent; // A single signalling circuit related event
|
|
class SignallingCircuit; // Abstract data circuit used by signalling
|
|
class SignallingCircuitRange; // A circuit range (set of circuits)
|
|
class SignallingCircuitGroup; // Group of data circuits used by signalling
|
|
class SignallingCircuitSpan; // A span in a circuit group
|
|
class SignallingInterface; // Abstract digital signalling interface (hardware access)
|
|
class SignallingReceiver; // Abstract Layer 2 packet data receiver
|
|
struct SignallingFlags; // Description of parameter flags
|
|
class SignallingUtils; // Library wide services and data provider
|
|
// Analog lines
|
|
class AnalogLine; // An analog line
|
|
class AnalogLineEvent; // A single analog line related event
|
|
class AnalogLineGroup; // A group of analog lines
|
|
// SS7
|
|
class SS7PointCode; // SS7 Code Point
|
|
class SS7Label; // SS7 Routing Label
|
|
class SS7MSU; // A block of data that holds a Message Signal Unit
|
|
class SIGTRAN; // Abstract SIGTRAN component
|
|
class SIGTransport; // Abstract transport for SIGTRAN
|
|
class ASPUser; // Abstract SS7 ASP user interface
|
|
class SCCP; // Abstract SS7 SCCP interface
|
|
class SCCPUser; // Abstract SS7 SCCP user interface
|
|
class TCAPUser; // Abstract SS7 TCAP user interface
|
|
class SS7L2User; // Abstract user of SS7 layer 2 (data link) message transfer part
|
|
class SS7Layer2; // Abstract SS7 layer 2 (data link) message transfer part
|
|
class SS7L3User; // Abstract user of SS7 layer 3 (network) message transfer part
|
|
class SS7Layer3; // Abstract SS7 layer 3 (network) message transfer part
|
|
class SS7Layer4; // Abstract SS7 layer 4 (application) protocol
|
|
class SS7Route; // A SS7 MSU route
|
|
class SS7Router; // Main router for SS7 message transfer and applications
|
|
class SS7M2PA; // SIGTRAN MTP2 User Peer-to-Peer Adaptation Layer
|
|
class SS7M2UA; // SIGTRAN MTP2 User Adaptation Layer
|
|
class SS7M3UA; // SIGTRAN MTP3 User Adaptation Layer
|
|
class SS7MTP2; // SS7 Layer 2 implementation on top of a hardware interface
|
|
class SS7MTP3; // SS7 Layer 3 implementation on top of Layer 2
|
|
class SS7MsgSNM; // SNM signalling message
|
|
class SS7MsgMTN; // MTN signalling message
|
|
class SS7MsgISUP; // ISUP signalling message
|
|
class SS7Management; // SS7 SNM implementation
|
|
class SS7Maintenance; // SS7 MTN implementation
|
|
class SS7ISUPCall; // A SS7 ISUP call
|
|
class SS7ISUP; // SS7 ISUP implementation
|
|
class SS7BICC; // SS7 BICC implementation
|
|
class SS7TUP; // SS7 TUP implementation
|
|
class SS7SCCP; // SS7 SCCP implementation
|
|
class SS7SUA; // SIGTRAN SCCP User Adaptation Layer
|
|
class SS7ASP; // SS7 ASP implementation
|
|
class SS7TCAP; // SS7 TCAP implementation
|
|
// ISDN
|
|
class ISDNLayer2; // Abstract ISDN layer 2 (Q.921) message transport
|
|
class ISDNLayer3; // Abstract ISDN layer 3 (Q.931) message transport
|
|
class ISDNFrame; // An ISDN Q.921 frame
|
|
class ISDNQ921; // ISDN Q.921 implementation on top of a hardware interface
|
|
class ISDNQ921Passive; // Stateless ISDN Q.921 implementation on top of a hardware interface
|
|
class ISDNQ921Management; // ISDN Layer 2 BRI TEI management or PRI with D-channel(s) backup
|
|
class ISDNIUA; // SIGTRAN ISDN Q.921 User Adaptation Layer
|
|
class ISDNQ931IE; // A Q.931 ISDN Layer 3 message Information Element
|
|
class ISDNQ931Message; // A Q.931 ISDN Layer 3 message
|
|
class ISDNQ931IEData; // A Q.931 message IE data processor
|
|
class ISDNQ931State; // Q.931 ISDN call and call controller state
|
|
class ISDNQ931Call; // A Q.931 ISDN call
|
|
class ISDNQ931CallMonitor; // A Q.931 ISDN call monitor
|
|
class ISDNQ931ParserData; // Q.931 message parser data
|
|
class ISDNQ931; // ISDN Q.931 implementation on top of Q.921
|
|
class ISDNQ931Monitor; // ISDN Q.931 implementation on top of Q.921 of call controller monitor
|
|
|
|
// Macro to create a factory that builds a component by class name
|
|
#define YSIGFACTORY(clas) \
|
|
class clas ## Factory : public SignallingFactory \
|
|
{ \
|
|
protected: \
|
|
virtual SignallingComponent* create(const String& type, const NamedList& name) \
|
|
{ return (type == #clas) ? new clas : 0; } \
|
|
}; \
|
|
static clas ## Factory s_ ## clas ## Factory
|
|
|
|
// Macro to create a factory that calls a component's static create method
|
|
#define YSIGFACTORY2(clas) \
|
|
class clas ## Factory : public SignallingFactory \
|
|
{ \
|
|
protected: \
|
|
virtual SignallingComponent* create(const String& type, const NamedList& name) \
|
|
{ return clas::create(type,name); } \
|
|
}; \
|
|
static clas ## Factory s_ ## clas ## Factory
|
|
|
|
// Macro to call the factory creation method and return the created component
|
|
#define YSIGCREATE(type,name) (static_cast<type*>(SignallingFactory::buildInternal(#type,name)))
|
|
|
|
/**
|
|
* This class is a generic data dumper with libpcap compatibility
|
|
* @short A generic data dumper
|
|
*/
|
|
class YSIG_API SignallingDumper
|
|
{
|
|
public:
|
|
/**
|
|
* Type of dumper output
|
|
*/
|
|
enum Type {
|
|
Raw,
|
|
Hexa,
|
|
Hdlc,
|
|
Q921,
|
|
Q931,
|
|
Mtp2,
|
|
Mtp3,
|
|
Sccp,
|
|
};
|
|
|
|
/**
|
|
* Constructor
|
|
* @param type Type of the output desired
|
|
* @param network True if we are the network side of the link
|
|
*/
|
|
SignallingDumper(Type type = Hexa, bool network = false);
|
|
|
|
/**
|
|
* Destructor, closes the output
|
|
*/
|
|
~SignallingDumper();
|
|
|
|
/**
|
|
* Get the type of the dumper
|
|
* @return Type of the dumper object
|
|
*/
|
|
inline Type type() const
|
|
{ return m_type; }
|
|
|
|
/**
|
|
* Get the network side flag
|
|
* @return True if we are the network side
|
|
*/
|
|
inline bool network() const
|
|
{ return m_network; }
|
|
|
|
/**
|
|
* Check if the dumper is active
|
|
* @return True if the object will actually send data to something
|
|
*/
|
|
bool active() const;
|
|
|
|
/**
|
|
* Terminate the dump session, close the output
|
|
*/
|
|
void terminate();
|
|
|
|
/**
|
|
* Set a new output stream
|
|
* @param stream New stream for output, NULL to terminate
|
|
* @param writeHeader True to write the header (if any) at start of stream
|
|
*/
|
|
void setStream(Stream* stream = 0, bool writeHeader = true);
|
|
|
|
/**
|
|
* Dump the provided data
|
|
* @param buf Pointer to buffer to dump
|
|
* @param len Length of the data
|
|
* @param sent True if data is being sent, false if is being received
|
|
* @param link Link number (relevant to MTP2 only)
|
|
* @return True if the data was dumped successfully
|
|
*/
|
|
bool dump(void* buf, unsigned int len, bool sent = false, int link = 0);
|
|
|
|
/**
|
|
* Dump the provided data
|
|
* @param data Buffer to dump
|
|
* @param sent True if data is being sent, false if is being received
|
|
* @param link Link number (relevant to MTP2 only)
|
|
* @return True if the data was dumped successfully
|
|
*/
|
|
inline bool dump(const DataBlock& data, bool sent = false, int link = 0)
|
|
{ return dump(data.data(),data.length(),sent,link); }
|
|
|
|
/**
|
|
* Create a file to dump data in it. The file is opened/created in write only, binary mode
|
|
* @param dbg DebugEnabler requesting the operation (used for debug message on failure)
|
|
* @param filename The file name to use
|
|
* @param type The dumper type
|
|
* @param network True to create a network side dumper
|
|
* @param create True to create the file if doesn't exist
|
|
* @param append Append to an existing file. If false and the file already exists, it will be truncated
|
|
* @return SignallingDumper pointer on success, 0 on failure
|
|
*/
|
|
static SignallingDumper* create(DebugEnabler* dbg, const char* filename, Type type,
|
|
bool network = false, bool create = true, bool append = false);
|
|
|
|
/**
|
|
* Create a dumper from an already existing stream
|
|
* @param stream Stream to use for output, will be owned by dumper
|
|
* @param type The dumper type
|
|
* @param network True to create a network side dumper
|
|
* @param writeHeader True to write the header (if any) at start of stream
|
|
* @return SignallingDumper pointer on success, 0 on failure
|
|
*/
|
|
static SignallingDumper* create(Stream* stream, Type type, bool network = false, bool writeHeader = true);
|
|
|
|
private:
|
|
void head();
|
|
Type m_type;
|
|
bool m_network;
|
|
Stream* m_output;
|
|
};
|
|
|
|
/**
|
|
* A generic base class for components capable of creating data dumps
|
|
* @short A data dumping capable component
|
|
*/
|
|
class YSIG_API SignallingDumpable
|
|
{
|
|
public:
|
|
/**
|
|
* Destructor - destroys the data dumper
|
|
*/
|
|
inline ~SignallingDumpable()
|
|
{ setDumper(); }
|
|
|
|
protected:
|
|
/**
|
|
* Constructor
|
|
* @param type Default type of the data dumper
|
|
* @param network True if we are the network side of the link
|
|
*/
|
|
inline SignallingDumpable(SignallingDumper::Type type, bool network = false)
|
|
: m_type(type), m_dumpNet(network), m_dumper(0)
|
|
{ }
|
|
|
|
/**
|
|
* Dump the provided data if the dumper is valid
|
|
* @param buf Pointer to buffer to dump
|
|
* @param len Length of the data
|
|
* @param sent True if data is being sent, false if is being received
|
|
* @param link Link number (relevant to MTP2 only)
|
|
* @return True if the data was dumped successfully
|
|
*/
|
|
inline bool dump(void* buf, unsigned int len, bool sent = false, int link = 0)
|
|
{ return (m_dumper && m_dumper->dump(buf,len,sent,link)); }
|
|
|
|
/**
|
|
* Dump data if the dumper is valid
|
|
* @param data Buffer to dump
|
|
* @param sent True if data is being sent, false if is being received
|
|
* @param link Link number (relevant to MTP2 only)
|
|
* @return True if the data was dumped successfully
|
|
*/
|
|
inline bool dump(const DataBlock& data, bool sent = false, int link = 0)
|
|
{ return dump(data.data(),data.length(),sent,link); }
|
|
|
|
/**
|
|
* Set the dump network side flag
|
|
* @param network True to dump as network side, false othervise
|
|
*/
|
|
inline void setDumpNetwork(bool network)
|
|
{ m_dumpNet = network; }
|
|
|
|
/**
|
|
* Set or remove the data dumper
|
|
* @param dumper Pointer to the data dumper object, 0 to remove
|
|
*/
|
|
void setDumper(SignallingDumper* dumper = 0);
|
|
|
|
/**
|
|
* Set or remove a file data dumper
|
|
* @param name Name of the file to dump to, empty to remove dumper
|
|
* @param create True to create the file if doesn't exist
|
|
* @param append Append to an existing file. If false and the file already exists, it will be truncated
|
|
* @return True if the file dumper was created or removed
|
|
*/
|
|
bool setDumper(const String& name, bool create = true, bool append = false);
|
|
|
|
/**
|
|
* Handle dumper related control on behalf of the owning component
|
|
* @param params Control parameters to handle
|
|
* @param owner Optional owning component
|
|
* @return True if control operation was applied
|
|
*/
|
|
bool control(NamedList& params, SignallingComponent* owner = 0);
|
|
|
|
private:
|
|
SignallingDumper::Type m_type;
|
|
bool m_dumpNet;
|
|
SignallingDumper* m_dumper;
|
|
};
|
|
|
|
/**
|
|
* Timer management class. Used to manage timeouts. The time is kept in miliseconds
|
|
* @short A signalling timer
|
|
*/
|
|
class YSIG_API SignallingTimer
|
|
{
|
|
public:
|
|
/**
|
|
* Constructor
|
|
* @param interval The timeout interval. Set to 0 to disable
|
|
* @param time Optional timeout value. If non 0, the timer is started
|
|
*/
|
|
inline SignallingTimer(u_int64_t interval, u_int64_t time = 0)
|
|
: m_interval(interval), m_timeout(0)
|
|
{ if (time) start(time); }
|
|
|
|
/**
|
|
* Set the timeout interval
|
|
* @param value The new timeout value
|
|
*/
|
|
inline void interval(u_int64_t value)
|
|
{ m_interval = value; }
|
|
|
|
/**
|
|
* Set the timeout interval from a list of parameters. The interval value is
|
|
* checked to be at least minVal or 0 if allowDisable is true
|
|
* @param params The list of parameters
|
|
* @param param The name of the parameter containing the timer interval value
|
|
* @param minVal Minimum value allowed for the timer interval
|
|
* @param defVal Default value if it fails to get one from the given parameter
|
|
* @param allowDisable True to allow 0 for the timer interval
|
|
* @param sec True if the interval value if given in seconds
|
|
*/
|
|
inline void interval(const NamedList& params, const char* param,
|
|
unsigned int minVal, unsigned int defVal, bool allowDisable, bool sec = false)
|
|
{
|
|
m_interval = (u_int64_t)params.getIntValue(param,defVal);
|
|
if (m_interval) {
|
|
if (m_interval < minVal)
|
|
m_interval = minVal;
|
|
}
|
|
else if (!allowDisable)
|
|
m_interval = minVal;
|
|
if (sec)
|
|
m_interval *= 1000;
|
|
}
|
|
|
|
/**
|
|
* Get the timeout interval
|
|
* @return The timeout interval
|
|
*/
|
|
inline u_int64_t interval() const
|
|
{ return m_interval; }
|
|
|
|
/**
|
|
* Start the timer if enabled (interval is positive)
|
|
* @param time Time to be added to the interval to set the timeout point
|
|
*/
|
|
inline void start(u_int64_t time = Time::msecNow())
|
|
{ if (m_interval) m_timeout = time + m_interval; }
|
|
|
|
/**
|
|
* Stop the timer
|
|
*/
|
|
inline void stop()
|
|
{ m_timeout = 0; }
|
|
|
|
/**
|
|
* Check if the timer is started
|
|
* @return True if the timer is started
|
|
*/
|
|
inline bool started()
|
|
{ return m_timeout > 0; }
|
|
|
|
/**
|
|
* Check if the timer is started and timed out
|
|
* @param time The time to compare with
|
|
* @return True if the timer timed out
|
|
*/
|
|
inline bool timeout(u_int64_t time = Time::msecNow())
|
|
{ return started() && (m_timeout < time); }
|
|
|
|
private:
|
|
u_int64_t m_interval; // Timer interval
|
|
u_int64_t m_timeout; // Timeout value
|
|
};
|
|
|
|
/**
|
|
* Counter management class. Keep a value between 0 and a given maximum one
|
|
* @short A counter class
|
|
*/
|
|
class YSIG_API SignallingCounter
|
|
{
|
|
public:
|
|
/**
|
|
* Constructor
|
|
* @param maxVal The maximum value for the counter
|
|
*/
|
|
inline SignallingCounter(u_int32_t maxVal)
|
|
: m_max(maxVal), m_count(0)
|
|
{ }
|
|
|
|
/**
|
|
* Set the maximum value for the counter
|
|
* @param value The new maximum value for the counter
|
|
*/
|
|
inline void maxVal(u_int32_t value)
|
|
{ m_max = value; }
|
|
|
|
/**
|
|
* Get the maximum value for the counter
|
|
* @return The maximum value for the counter
|
|
*/
|
|
inline u_int32_t maxVal() const
|
|
{ return m_max; }
|
|
|
|
/**
|
|
* Get the current value of the counter
|
|
* @return The current value of the counter
|
|
*/
|
|
inline u_int32_t count() const
|
|
{ return m_count; }
|
|
|
|
/**
|
|
* Reset the counter's value
|
|
* @param down True to reset to 0, false to reset to maxVal()
|
|
*/
|
|
inline void reset(bool down = true)
|
|
{ m_count = down ? 0 : m_max; }
|
|
|
|
/**
|
|
* Increment the counter's value if it can
|
|
* @return False if the counter is full (reached the maximum value)
|
|
*/
|
|
inline bool inc()
|
|
{
|
|
if (full())
|
|
return false;
|
|
m_count++;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Decrement the counter's value if it can
|
|
* @return False if the counter is empty (reached 0)
|
|
*/
|
|
inline bool dec()
|
|
{
|
|
if (empty())
|
|
return false;
|
|
m_count--;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Check if the counter is empty (the value is 0)
|
|
* @return True if the counter is empty
|
|
*/
|
|
inline bool empty() const
|
|
{ return m_count == 0; }
|
|
|
|
/**
|
|
* Check if the counter is full (the value reached the maximum)
|
|
* @return True if the counter is full
|
|
*/
|
|
inline bool full() const
|
|
{ return m_count == maxVal(); }
|
|
|
|
private:
|
|
u_int32_t m_max; // Maximum counter value
|
|
u_int32_t m_count; // Current counter value
|
|
};
|
|
|
|
/**
|
|
* A factory that constructs various elements by name
|
|
* @short A signalling component factory
|
|
*/
|
|
class YSIG_API SignallingFactory : public GenObject
|
|
{
|
|
public:
|
|
/**
|
|
* Constructor, adds the factory to the global list
|
|
* @param fallback True to add this factory at the end of the priority list
|
|
*/
|
|
SignallingFactory(bool fallback = false);
|
|
|
|
/**
|
|
* Destructor, removes the factory from list
|
|
*/
|
|
virtual ~SignallingFactory();
|
|
|
|
/**
|
|
* Builds a component given its name and arbitrary parameters
|
|
* @param type The type of the component that should be returned
|
|
* @param name Name of the requested component and additional parameters
|
|
* @return Pointer to the created component, NULL on failure
|
|
*/
|
|
static SignallingComponent* build(const String& type, const NamedList* name = 0);
|
|
|
|
/**
|
|
* This method is for internal use only and must not be called directly
|
|
* @param type The name of the interface that should be returned
|
|
* @param name Name of the requested component and additional parameters
|
|
* @return Raw pointer to the requested interface of the component, NULL on failure
|
|
*/
|
|
static void* buildInternal(const String& type, const NamedList* name);
|
|
|
|
protected:
|
|
/**
|
|
* Creates a component given its name and arbitrary parameters
|
|
* @param type The name of the interface that should be returned
|
|
* @param name Name of the requested component and additional parameters
|
|
* @return Pointer to the created component
|
|
*/
|
|
virtual SignallingComponent* create(const String& type, const NamedList& name) = 0;
|
|
};
|
|
|
|
/**
|
|
* Interface to an abstract signalling component that is managed by an engine.
|
|
* The engine will periodically poll each component to keep them alive.
|
|
* @short Abstract signalling component that can be managed by the engine
|
|
*/
|
|
class YSIG_API SignallingComponent : public RefObject, public DebugEnabler
|
|
{
|
|
YCLASS(SignallingComponent,RefObject)
|
|
friend class SignallingEngine;
|
|
public:
|
|
/**
|
|
* Destructor, detaches the engine and other components
|
|
*/
|
|
virtual ~SignallingComponent();
|
|
|
|
/**
|
|
* Get the component's name so it can be used for list searches
|
|
* @return A reference to the name by which the component is known to engine
|
|
*/
|
|
virtual const String& toString() const;
|
|
|
|
/**
|
|
* Configure and initialize the component and any subcomponents it may have
|
|
* @param config Optional configuration parameters override
|
|
* @return True if the component was initialized properly
|
|
*/
|
|
virtual bool initialize(const NamedList* config);
|
|
|
|
/**
|
|
* Query or modify component's settings or operational parameters
|
|
* @param params The list of parameters to query or change
|
|
* @return True if the control operation was executed
|
|
*/
|
|
virtual bool control(NamedList& params);
|
|
|
|
/**
|
|
* Set the @ref TelEngine::SignallingEngine that manages this component
|
|
* and any subcomponent of it
|
|
* @param eng Pointer to the engine that will manage this component
|
|
*/
|
|
virtual void engine(SignallingEngine* eng);
|
|
|
|
/**
|
|
* Get the @ref TelEngine::SignallingEngine that manages this component
|
|
* @return Pointer to engine or NULL if not managed by an engine
|
|
*/
|
|
inline SignallingEngine* engine() const
|
|
{ return m_engine; }
|
|
|
|
/**
|
|
* Conditionally set the debug level of the component
|
|
* @param level Desired debug level, negative for no change
|
|
* @return Current debug level
|
|
*/
|
|
inline int debugLevel(int level)
|
|
{ return (level >= 0) ? DebugEnabler::debugLevel(level) : DebugEnabler::debugLevel(); }
|
|
|
|
protected:
|
|
/**
|
|
* Constructor with a default empty component name
|
|
* @param name Name of this component
|
|
* @param params Optional pointer to creation parameters
|
|
*/
|
|
SignallingComponent(const char* name = 0, const NamedList* params = 0);
|
|
|
|
/**
|
|
* This method is called to clean up and destroy the object after the
|
|
* reference counter becomes zero
|
|
*/
|
|
void destroyed();
|
|
|
|
/**
|
|
* Insert another component in the same engine as this one.
|
|
* This method should be called for every component we attach.
|
|
* @param component Pointer to component to insert in engine
|
|
*/
|
|
void insert(SignallingComponent* component);
|
|
|
|
/**
|
|
* Detach this component from all its links - components and engine.
|
|
* Reimplement this method in all components that keep pointers to
|
|
* other components.
|
|
* The default implementation detaches from the engine.
|
|
*/
|
|
virtual void detach();
|
|
|
|
/**
|
|
* Method called periodically by the engine to keep everything alive
|
|
* @param when Time to use as computing base for events and timeouts
|
|
*/
|
|
virtual void timerTick(const Time& when);
|
|
|
|
/**
|
|
* Change the name of the component after it was constructed
|
|
* @param name Name of this component
|
|
*/
|
|
void setName(const char* name);
|
|
|
|
/**
|
|
* Adjust (decrease only) the desired maximum time until next tick.
|
|
* Can be called only from within timerTick()
|
|
* @param usec Desired time until next engine's timerTick() call in usec
|
|
* @return Timer sleep in usec after applying the current change
|
|
*/
|
|
unsigned long tickSleep(unsigned long usec = 1000000) const;
|
|
|
|
private:
|
|
SignallingEngine* m_engine;
|
|
String m_name;
|
|
};
|
|
|
|
/**
|
|
* The engine is the center of all SS7 or ISDN applications.
|
|
* It is used as a base to build the protocol stack from components.
|
|
* @short Main signalling component holder
|
|
*/
|
|
class YSIG_API SignallingEngine : public DebugEnabler, public Mutex
|
|
{
|
|
friend class SignallingComponent;
|
|
friend class SignallingThreadPrivate;
|
|
public:
|
|
/**
|
|
* Constructor of an empty engine
|
|
* @param name The debug name of this engine
|
|
*/
|
|
SignallingEngine(const char* name = "signalling");
|
|
|
|
/**
|
|
* Destructor, removes all components
|
|
*/
|
|
virtual ~SignallingEngine();
|
|
|
|
/**
|
|
* Insert a component in the engine, lock the list while doing so
|
|
* @param component Pointer to component to insert in engine
|
|
*/
|
|
void insert(SignallingComponent* component);
|
|
|
|
/**
|
|
* Remove a component from the engine, lock the list while doing so
|
|
* @param component Pointer to component to remove from engine
|
|
*/
|
|
void remove(SignallingComponent* component);
|
|
|
|
/**
|
|
* Remove and destroy a component from the engine by name
|
|
* @param name Name of component to remove from engine
|
|
* @return True if a component was found and destroyed
|
|
*/
|
|
bool remove(const String& name);
|
|
|
|
/**
|
|
* Retrive a component by name, lock the list while searching for it
|
|
* @param name Name of the component to find
|
|
* @return Pointer to component found or NULL
|
|
*/
|
|
SignallingComponent* find(const String& name);
|
|
|
|
/**
|
|
* Retrive a component by name and class, lock the list while searching for it
|
|
* @param name Name of the component to find, empty to find any of the type
|
|
* @param type Class or base class of the component to find, empty to match any
|
|
* @param start Component to start searching from, search all list if NULL
|
|
* @return Pointer to component found or NULL
|
|
*/
|
|
SignallingComponent* find(const String& name, const String& type, const SignallingComponent* start = 0);
|
|
|
|
/**
|
|
* Retrive and reference an existing component, create by factory if not present
|
|
* @param type Class or base class of the component to find or create
|
|
* @param params Name of component to find or create and creation parameters
|
|
* @param init Set to true to initialize a newly created component
|
|
* @return Pointer to component found or created, NULL on failure
|
|
*/
|
|
SignallingComponent* build(const String& type, const NamedList& params, bool init = false);
|
|
|
|
/**
|
|
* Apply a control operation to all components in the engine
|
|
* @param params The list of parameters to query or change
|
|
* @return True if the control operation was executed by at least one component
|
|
*/
|
|
bool control(NamedList& params);
|
|
|
|
/**
|
|
* Check if a component is in the engine's list
|
|
* @param component Pointer to component to check
|
|
* @return True if the component is in the engine's list
|
|
*/
|
|
bool find(const SignallingComponent* component);
|
|
|
|
/**
|
|
* Starts the worker thread that keeps components alive
|
|
* @param name Static name of the thread
|
|
* @param prio Thread's priority
|
|
* @param usec How long to sleep between iterations in usec, 0 to use library default
|
|
* @return True if (already) started, false if an error occured
|
|
*/
|
|
bool start(const char* name = "Sig Engine", Thread::Priority prio = Thread::Normal, unsigned long usec = 0);
|
|
|
|
/**
|
|
* Stops and destroys the worker thread if running
|
|
*/
|
|
void stop();
|
|
|
|
/**
|
|
* Return a pointer to the worker thread
|
|
* @return Pointer to running worker thread or NULL
|
|
*/
|
|
Thread* thread() const;
|
|
|
|
/**
|
|
* Adjust (decrease only) the desired maximum time until next tick.
|
|
* Can be called only from within timerTick()
|
|
* @param usec Desired time until next timerTick() call in usec
|
|
* @return Timer sleep in usec after applying the current change
|
|
*/
|
|
unsigned long tickSleep(unsigned long usec = 1000000);
|
|
|
|
/**
|
|
* Get the default engine tick sleep time in microseconds
|
|
* @return Default timer sleep in usec
|
|
*/
|
|
inline unsigned long tickDefault() const
|
|
{ return m_usecSleep; }
|
|
|
|
/**
|
|
* Helper template used to remove a component descendant from its engine,
|
|
* destroy it and set the received pointer to 0
|
|
* @param obj Reference to pointer (lvalue) to the object to remove and destroy
|
|
*/
|
|
template <class Obj> static inline void destruct(Obj*& obj)
|
|
{
|
|
if (!obj)
|
|
return;
|
|
if (obj->engine())
|
|
obj->engine()->remove(obj);
|
|
TelEngine::destruct(obj);
|
|
}
|
|
|
|
protected:
|
|
/**
|
|
* Method called periodically by the worker thread to keep everything alive
|
|
* @param when Time to use as computing base for events and timeouts
|
|
* @return Desired sleep (in usec) until thread's next tick interval
|
|
*/
|
|
virtual unsigned long timerTick(const Time& when);
|
|
|
|
/**
|
|
* The list of components managed by this engine
|
|
*/
|
|
ObjList m_components;
|
|
|
|
private:
|
|
SignallingThreadPrivate* m_thread;
|
|
bool m_listChanged;
|
|
unsigned long m_usecSleep;
|
|
unsigned long m_tickSleep;
|
|
};
|
|
|
|
/**
|
|
* Interface of protocol independent signalling message
|
|
* @short Abstract signalling message
|
|
*/
|
|
class YSIG_API SignallingMessage : public RefObject
|
|
{
|
|
YCLASS(SignallingMessage,RefObject)
|
|
public:
|
|
/**
|
|
* Constructor
|
|
* @param name Named list's name
|
|
*/
|
|
inline SignallingMessage(const char* name = 0)
|
|
: m_params(name)
|
|
{ }
|
|
|
|
/**
|
|
* Get the name of the message
|
|
* @return The name of the message
|
|
*/
|
|
inline const char* name() const
|
|
{ return m_params.c_str(); }
|
|
|
|
/**
|
|
* Get this message's parameter list
|
|
* @return This message's parameter list
|
|
*/
|
|
inline NamedList& params()
|
|
{ return m_params; }
|
|
|
|
protected:
|
|
/**
|
|
* Message parameter list
|
|
*/
|
|
NamedList m_params;
|
|
};
|
|
|
|
/**
|
|
* Interface of protocol independent signalling for phone calls
|
|
* @short Abstract phone call signalling
|
|
*/
|
|
class YSIG_API SignallingCallControl : public Mutex
|
|
{
|
|
friend class SignallingCall;
|
|
friend class SS7ISUPCall;
|
|
friend class ISDNQ931Call;
|
|
friend class ISDNQ931CallMonitor;
|
|
public:
|
|
/**
|
|
* Constructor
|
|
* @param params Call controller's parameters
|
|
* @param msgPrefix Optional prefix to be added before a decoded message's
|
|
* parameters or retrive message parameters from a list
|
|
*/
|
|
SignallingCallControl(const NamedList& params, const char* msgPrefix = 0);
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~SignallingCallControl();
|
|
|
|
/**
|
|
* Set exiting flag
|
|
*/
|
|
inline void setExiting()
|
|
{ m_exiting = true; }
|
|
|
|
/**
|
|
* Get exiting flag
|
|
* @return The exiting flag
|
|
*/
|
|
inline bool exiting() const
|
|
{ return m_exiting; }
|
|
|
|
/**
|
|
* Check the verify event flag. Reset it if true is returned
|
|
* @return True if the verify event flag is set
|
|
*/
|
|
inline bool verify()
|
|
{
|
|
Lock lock(this);
|
|
if (!m_verifyEvent)
|
|
return false;
|
|
m_verifyEvent = false;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Get the prefix used by this call controller when decoding message parameters or
|
|
* retrive message parameters from a list
|
|
* @return Message parameters prefix used by this call controller
|
|
*/
|
|
inline const String& msgPrefix() const
|
|
{ return m_msgPrefix; }
|
|
|
|
/**
|
|
* Get the circuit group attached to this call controller
|
|
* @return The circuit group attached to this call controller
|
|
*/
|
|
inline SignallingCircuitGroup* circuits() const
|
|
{ return m_circuits; }
|
|
|
|
/**
|
|
* Get the list of calls currently known by this call controller
|
|
* @return Reference to the list of calls
|
|
*/
|
|
inline const ObjList& calls() const
|
|
{ return m_calls; }
|
|
|
|
/**
|
|
* Attach/detach a circuit group to this call controller. Set group's allocation strategy.
|
|
* Set locked flags for all circuits belonging to the attached circuit group.
|
|
* Cleanup controller before detaching the group or attaching a new one
|
|
* This method is thread safe
|
|
* @param circuits Pointer to the SignallingCircuitGroup to attach. 0 to detach and force a cleanup
|
|
* @return Pointer to the old group that was detached, NULL if none or no change
|
|
*/
|
|
SignallingCircuitGroup* attach(SignallingCircuitGroup* circuits);
|
|
|
|
/**
|
|
* Reserve a circuit for later use. If the circuit list is 0, try to reserve a circuit from
|
|
* the group using its strategy. Release the given circuit before trying to reserve it.
|
|
* Set cic to 0 on failure.
|
|
* This method is thread safe
|
|
* @param cic Destination circuit
|
|
* @param checkLock Lock flags to check. If the given lock flags are set, reservation will fail
|
|
* @param range Optional range name to restrict circuit reservation within attached circuit group
|
|
* @param list Comma separated list of circuits
|
|
* @param mandatory The list is mandatory. If false and none of the circuits in
|
|
* the list are available, try to reserve a free one. Ignored if list is 0
|
|
* @param reverseRestrict Used when failed to reserve circuit from list. If true and the circuit allocation
|
|
* strategy includes any restriction (odd or even) use the opposite restriction to reserve a circuit.
|
|
* Ignored if mandatory is true
|
|
* @return False if the operation failed
|
|
*/
|
|
bool reserveCircuit(SignallingCircuit*& cic, const char* range = 0, int checkLock = -1,
|
|
const String* list = 0, bool mandatory = true, bool reverseRestrict = false);
|
|
|
|
/**
|
|
* Initiate a release of a circuit. Set cic to 0.
|
|
* This method is thread safe
|
|
* @param cic The circuit to release
|
|
* @param sync Synchronous release requested
|
|
* @return True if the circuit release was initiated
|
|
*/
|
|
bool releaseCircuit(SignallingCircuit*& cic, bool sync = false);
|
|
|
|
/**
|
|
* Initiate a release of a circuit from the attached group
|
|
* This method is thread safe
|
|
* @param code The circuit's code
|
|
* @param sync Synchronous release requested
|
|
* @return True if the circuit release was initiated
|
|
*/
|
|
bool releaseCircuit(unsigned int code, bool sync = false);
|
|
|
|
/**
|
|
* Cleanup
|
|
* @param reason Cleanup reason
|
|
*/
|
|
virtual void cleanup(const char* reason = "offline")
|
|
{ }
|
|
|
|
/**
|
|
* Iterate through the call list to get an event
|
|
* @param when The current time
|
|
* @return SignallingEvent pointer or 0 if no events
|
|
*/
|
|
virtual SignallingEvent* getEvent(const Time& when);
|
|
|
|
/**
|
|
* Create an outgoing call. Send a NewCall event with the given msg parameter
|
|
* @param msg Call parameters
|
|
* @param reason Failure reason if any
|
|
* @return Referenced SignallingCall pointer on success or 0 on failure
|
|
*/
|
|
virtual SignallingCall* call(SignallingMessage* msg, String& reason)
|
|
{ reason = "not-implemented"; return 0; }
|
|
|
|
/**
|
|
* Build the parameters of a Verify event
|
|
* @param params The list of parameters to fill
|
|
*/
|
|
virtual void buildVerifyEvent(NamedList& params)
|
|
{ }
|
|
|
|
protected:
|
|
/**
|
|
* Get the strategy used by the attached circuit group to allocate circuits
|
|
* @return The strategy used by the attached circuit group to allocate circuits
|
|
*/
|
|
inline int strategy() const
|
|
{ return m_strategy; }
|
|
|
|
/**
|
|
* Process an event received from a call. This will give to derived classes an opportunity
|
|
* to intercept events generated by their calls
|
|
* @param event The event
|
|
* @return True if the event was processed by the controller.
|
|
* False to deliver the event to the requestor
|
|
*/
|
|
virtual bool processEvent(SignallingEvent* event)
|
|
{ return false; }
|
|
|
|
/**
|
|
* Process an event received from a non-reserved circuit
|
|
* @param event The event, will be consumed and zeroed
|
|
* @param call Optional signalling call whose circuit generated the event
|
|
* @return Signalling event pointer or 0
|
|
*/
|
|
virtual SignallingEvent* processCircuitEvent(SignallingCircuitEvent*& event,
|
|
SignallingCall* call = 0)
|
|
{ TelEngine::destruct(event); return 0; }
|
|
|
|
/**
|
|
* Clear call list
|
|
*/
|
|
void clearCalls();
|
|
|
|
/**
|
|
* Remove a call from list
|
|
* @param call The call to remove
|
|
* @param del True to delete it. False to remove without destruct
|
|
*/
|
|
void removeCall(SignallingCall* call, bool del = false);
|
|
|
|
/**
|
|
* List of active calls
|
|
*/
|
|
ObjList m_calls;
|
|
|
|
/**
|
|
* Prefix to be added to decoded message parameters or
|
|
* retrive message parameters from a list
|
|
*/
|
|
String m_msgPrefix;
|
|
|
|
/**
|
|
* Draw attention to call controller's user that something changed by
|
|
* raising a Verify event
|
|
*/
|
|
bool m_verifyEvent;
|
|
|
|
/**
|
|
* Timer used to raise verify events
|
|
*/
|
|
SignallingTimer m_verifyTimer;
|
|
|
|
private:
|
|
SignallingCircuitGroup* m_circuits; // Circuit group
|
|
int m_strategy; // Strategy to allocate circuits for outgoing calls
|
|
bool m_exiting; // Call control is terminating. Generate a Disable event when no more calls
|
|
};
|
|
|
|
/**
|
|
* Interface of protocol independent phone call
|
|
* @short Abstract single phone call
|
|
*/
|
|
class YSIG_API SignallingCall : public RefObject, public Mutex
|
|
{
|
|
public:
|
|
/**
|
|
* Constructor
|
|
* @param controller The call controller owning this call
|
|
* @param outgoing Call direction (true for outgoing)
|
|
* @param signalOnly Just signalling (no voice) flag
|
|
*/
|
|
SignallingCall(SignallingCallControl* controller, bool outgoing, bool signalOnly = false);
|
|
|
|
/**
|
|
* Destructor, notifies the controller
|
|
*/
|
|
virtual ~SignallingCall();
|
|
|
|
/**
|
|
* Check if this is an outgoing call
|
|
* @return True if it's an outgoing call
|
|
*/
|
|
inline bool outgoing() const
|
|
{ return m_outgoing; }
|
|
|
|
/**
|
|
* Retreive the controller of this call
|
|
*/
|
|
inline SignallingCallControl* controller() const
|
|
{ return m_controller; }
|
|
|
|
/**
|
|
* Set this call's private user data
|
|
* @param data New user data
|
|
*/
|
|
inline void userdata(void* data)
|
|
{ m_private = data; }
|
|
|
|
/**
|
|
* Retreive the private user data of this call
|
|
* @return User data
|
|
*/
|
|
inline void* userdata() const
|
|
{ return m_private; }
|
|
|
|
/**
|
|
* Check if this call is just a signalling (no voice) one
|
|
* @return True if no audio data can be negotiated for this call
|
|
*/
|
|
inline bool signalOnly() const
|
|
{ return m_signalOnly; }
|
|
|
|
/**
|
|
* Send an event to this call
|
|
* @param event The event to send
|
|
* @return True if the operation succedded
|
|
*/
|
|
virtual bool sendEvent(SignallingEvent* event)
|
|
{ return false; }
|
|
|
|
/**
|
|
* Get an event from this call if not already got one
|
|
* This method is thread safe
|
|
* @param when The current time
|
|
* @return SignallingEvent pointer or 0 if no events or this call has a not terminated event
|
|
*/
|
|
virtual SignallingEvent* getEvent(const Time& when) = 0;
|
|
|
|
/**
|
|
* Event terminated notification. No event will be generated until
|
|
* the current event is terminated
|
|
* This method is thread safe
|
|
* @param event The terminated event
|
|
*/
|
|
virtual void eventTerminated(SignallingEvent* event);
|
|
|
|
protected:
|
|
/**
|
|
* Enqueue a received message.
|
|
* This method is thread safe
|
|
* @param msg The received message
|
|
*/
|
|
void enqueue(SignallingMessage* msg);
|
|
|
|
/**
|
|
* Dequeue a received message. Just return it if remove is false
|
|
* This method is thread safe
|
|
* @param remove True to remove the message from queue
|
|
* @return SignallingMessage pointer or 0 if no more messages
|
|
*/
|
|
SignallingMessage* dequeue(bool remove = true);
|
|
|
|
/**
|
|
* Clear incoming messages queue
|
|
*/
|
|
void clearQueue()
|
|
{
|
|
Lock lock(m_inMsgMutex);
|
|
m_inMsg.clear();
|
|
}
|
|
|
|
/**
|
|
* Last event generated by this call. Used to serialize events
|
|
*/
|
|
SignallingEvent* m_lastEvent;
|
|
|
|
private:
|
|
SignallingCallControl* m_controller; // Call controller this call belongs to
|
|
bool m_outgoing; // Call direction
|
|
bool m_signalOnly; // Just signalling flag
|
|
ObjList m_inMsg; // Incoming messages queue
|
|
Mutex m_inMsgMutex; // Lock incoming messages queue
|
|
void* m_private; // Private user data
|
|
};
|
|
|
|
/**
|
|
* An object holding a signalling event and related references
|
|
* @short A single signalling related event
|
|
*/
|
|
class YSIG_API SignallingEvent
|
|
{
|
|
public:
|
|
/**
|
|
* Type of the event
|
|
*/
|
|
enum Type {
|
|
Unknown = 0,
|
|
Generic,
|
|
// Call related
|
|
NewCall,
|
|
Accept,
|
|
Connect,
|
|
Complete,
|
|
Progress,
|
|
Ringing,
|
|
Answer,
|
|
Transfer,
|
|
Suspend,
|
|
Resume,
|
|
Release,
|
|
Info,
|
|
// Non-call related
|
|
Message,
|
|
Facility,
|
|
Circuit,
|
|
// Controller related
|
|
Enable,
|
|
Disable,
|
|
Reset,
|
|
Verify,
|
|
};
|
|
|
|
/**
|
|
* Constructor for a call related event
|
|
* @param type Type of the event
|
|
* @param message Message carried by the event
|
|
* @param call Call this event refers to
|
|
*/
|
|
SignallingEvent(Type type, SignallingMessage* message, SignallingCall* call);
|
|
|
|
/**
|
|
* Constructor for a controller related event
|
|
* @param type Type of the event
|
|
* @param message Message carried by the event
|
|
* @param controller Controller this event refers to
|
|
*/
|
|
SignallingEvent(Type type, SignallingMessage* message, SignallingCallControl* controller = 0);
|
|
|
|
/**
|
|
* Constructor for a signalling circuit related event
|
|
* @param event The event signaled by the circuit, will be consumed and zeroed
|
|
* @param call Call this event refers to
|
|
*/
|
|
SignallingEvent(SignallingCircuitEvent*& event, SignallingCall* call);
|
|
|
|
/**
|
|
* Destructor, dereferences any resources, notify the signalling call of termination
|
|
*/
|
|
virtual ~SignallingEvent();
|
|
|
|
/**
|
|
* Get the string associated with this event's type
|
|
* @return The string associated with this event's type, if any
|
|
*/
|
|
inline const char* name() const
|
|
{ return typeName(type()); }
|
|
|
|
/**
|
|
* Get the type of the event
|
|
* @return Type of event, may be unknown
|
|
*/
|
|
inline Type type() const
|
|
{ return m_type; }
|
|
|
|
/**
|
|
* Get the call that generated this event, may be NULL
|
|
*/
|
|
inline SignallingCall* call() const
|
|
{ return m_call; }
|
|
|
|
/**
|
|
* Get the message that generated this event, may be NULL
|
|
*/
|
|
inline SignallingMessage* message() const
|
|
{ return m_message; }
|
|
|
|
/**
|
|
* Retrive the controller of the call
|
|
*/
|
|
inline SignallingCallControl* controller() const
|
|
{ return m_controller; }
|
|
|
|
/**
|
|
* Retrive the circuit event
|
|
*/
|
|
inline SignallingCircuitEvent* cicEvent() const
|
|
{ return m_cicEvent; }
|
|
|
|
/**
|
|
* Get the text associated with a given event type for debug purposes
|
|
* @param t The requested type
|
|
* @return The text associated with the given type
|
|
*/
|
|
static inline const char* typeName(Type t)
|
|
{ return lookup(t,s_types,0); }
|
|
|
|
/**
|
|
* Send this event through the call that generated it
|
|
* @return True if there was a call and the operation succedded
|
|
*/
|
|
bool sendEvent();
|
|
|
|
private:
|
|
Type m_type;
|
|
SignallingMessage* m_message;
|
|
SignallingCall* m_call;
|
|
SignallingCallControl* m_controller;
|
|
SignallingCircuitEvent* m_cicEvent;
|
|
static TokenDict s_types[];
|
|
};
|
|
|
|
/**
|
|
* An object holding a signalling circuit event and related references
|
|
* @short A single signalling circuit related event
|
|
*/
|
|
class YSIG_API SignallingCircuitEvent : public NamedList
|
|
{
|
|
public:
|
|
/**
|
|
* Type of the event
|
|
*/
|
|
enum Type {
|
|
Unknown = 0,
|
|
Dtmf = 1, // Transfer tones: param: tone
|
|
// Analog line events
|
|
Timeout = 10, //
|
|
Polarity = 11, // Line's polarity changed
|
|
StartLine = 15, // Initialize FXO line
|
|
LineStarted = 16, // FXO line initialized: send number
|
|
DialComplete = 17, // FXO line completed dialing the number
|
|
OnHook = 20, // The hook is down
|
|
OffHook = 21, // The hook is up
|
|
RingBegin = 22, // Start ringing
|
|
RingEnd = 23, // Stop ringing
|
|
RingerOn = 30, // An FXS started the FXO's ringer
|
|
RingerOff = 31, // An FXS stopped the FXO's ringer
|
|
Wink = 32, // On hook momentarily
|
|
Flash = 33, // Off hook momentarily
|
|
PulseStart = 40, // Pulse dialing start
|
|
PulseDigit = 41, // Transfer pulse digits: param: pulse
|
|
// Remote circuit events
|
|
Connect = 50, // Request connect
|
|
Disconnect = 51, // Request disconnect
|
|
Connected = 52, // Connected notification
|
|
Disconnected = 53, // Disconnected notification
|
|
// Errors
|
|
Alarm = 100, // Param: alarms (comma separated list of strings)
|
|
NoAlarm = 101, // No more alarms
|
|
};
|
|
|
|
/**
|
|
* Constructor for a circuit related event
|
|
* @param cic The circuit that generated this event
|
|
* @param type Event type as enumeration
|
|
* @param name Optional name for the named list
|
|
*/
|
|
SignallingCircuitEvent(SignallingCircuit* cic, Type type, const char* name = 0);
|
|
|
|
/**
|
|
* Destructor, dereferences any resources
|
|
*/
|
|
virtual ~SignallingCircuitEvent();
|
|
|
|
/**
|
|
* Get the type of this event
|
|
* @return The type of this event
|
|
*/
|
|
inline Type type() const
|
|
{ return m_type; }
|
|
|
|
/**
|
|
* Get the circuit that generated this event
|
|
* @return The circuit that generated this event
|
|
*/
|
|
inline SignallingCircuit* circuit()
|
|
{ return m_circuit; }
|
|
|
|
/**
|
|
* Send this event through the circuit. Release (delete) the event
|
|
* @return True if the operation succeded
|
|
*/
|
|
bool sendEvent();
|
|
|
|
private:
|
|
SignallingCircuit* m_circuit;
|
|
Type m_type;
|
|
};
|
|
|
|
/**
|
|
* Interface to an abstract voice/data circuit referenced by signalling
|
|
* @short Abstract data circuit used by signalling
|
|
*/
|
|
class YSIG_API SignallingCircuit : public RefObject
|
|
{
|
|
YCLASS(SignallingCircuit,RefObject)
|
|
friend class SignallingCircuitGroup;
|
|
friend class SignallingCircuitEvent;
|
|
public:
|
|
/**
|
|
* Type of the circuit hardware or transport
|
|
*/
|
|
enum Type {
|
|
Unknown = 0,
|
|
Local, // not really a circuit
|
|
TDM,
|
|
RTP,
|
|
IAX,
|
|
};
|
|
|
|
/**
|
|
* Status of the circuit
|
|
*/
|
|
enum Status {
|
|
Missing = 0,
|
|
Disabled,
|
|
Idle,
|
|
Reserved,
|
|
Starting,
|
|
Stopping,
|
|
Connected,
|
|
};
|
|
|
|
/**
|
|
* Lock circuit flags
|
|
*/
|
|
enum LockFlags {
|
|
LockLocalHWFail = 0x0001, // Local side of the circuit is locked due to HW failure
|
|
LockLocalMaint = 0x0002, // Local side of the circuit is locked for maintenance
|
|
LockLocalHWFailChg = 0x0010, // Local HW failure flag changed
|
|
LockLocalMaintChg = 0x0020, // Local maintenance flag changed
|
|
LockRemoteHWFail = 0x0100, // Remote side of the circuit is locked due to HW failure
|
|
LockRemoteMaint = 0x0200, // Remote side of the circuit is locked for maintenance
|
|
LockRemoteHWFailChg = 0x1000, // Remote HW failure flag changed
|
|
LockRemoteMaintChg = 0x2000, // Remote maintenance flag changed
|
|
// Masks used to test lock conditions
|
|
LockLocal = LockLocalHWFail | LockLocalMaint,
|
|
LockRemote = LockRemoteHWFail | LockRemoteMaint,
|
|
LockLocked = LockLocal | LockRemote,
|
|
LockLocalChg = LockLocalHWFailChg | LockLocalMaintChg,
|
|
LockRemoteChg = LockRemoteHWFailChg | LockRemoteMaintChg,
|
|
LockChanged = LockLocalChg | LockRemoteChg,
|
|
};
|
|
|
|
/**
|
|
* Destructor. Clear event list
|
|
*/
|
|
virtual ~SignallingCircuit();
|
|
|
|
/**
|
|
* Initiate a status transition
|
|
* @param newStat Desired new status
|
|
* @param sync Synchronous status change requested
|
|
* @return True if status change has been initiated
|
|
*/
|
|
virtual bool status(Status newStat, bool sync = false)
|
|
{ m_status = newStat; return true; }
|
|
|
|
/**
|
|
* Get the type of this circuit
|
|
* @return Enumerated type of circuit
|
|
*/
|
|
inline Type type() const
|
|
{ return m_type; }
|
|
|
|
/**
|
|
* Get the status of this circuit
|
|
* @return Enumerated status of circuit
|
|
*/
|
|
inline Status status() const
|
|
{ return m_status; }
|
|
|
|
/**
|
|
* Check if the given lock flags are set
|
|
* @param flags The lock flags to check. -1 to check all flags
|
|
* @return The lock flags of this circuit masked by the given flags
|
|
*/
|
|
inline int locked(int flags = -1) const
|
|
{ return (m_lock & flags); }
|
|
|
|
/**
|
|
* Set the given lock flags of this circuit
|
|
* @param flags The lock flags to set
|
|
*/
|
|
inline void setLock(int flags)
|
|
{ m_lock |= flags; }
|
|
|
|
/**
|
|
* Reset the given lock flags of this circuit
|
|
* @param flags The lock flags to reset
|
|
*/
|
|
inline void resetLock(int flags)
|
|
{ m_lock &= ~flags; }
|
|
|
|
/**
|
|
* Set the format of the data transported through this circuit
|
|
* @param format The new data format
|
|
* @param direction The direction to be updated. -1 means to the lower layer, 1 from the lower layer, 0 both directions
|
|
* @return True if the operation succeedded (format changed)
|
|
*/
|
|
virtual bool updateFormat(const char* format, int direction)
|
|
{ return false; }
|
|
|
|
/**
|
|
* Set circuit data or trigger some action
|
|
* @param param The data to update or the action to trigger
|
|
* @param value The data value or action parameter
|
|
* @return True on success
|
|
*/
|
|
virtual bool setParam(const String& param, const String& value)
|
|
{ return false; }
|
|
|
|
/**
|
|
* Set circuit data from a list of parameters
|
|
* @param params Parameter list to set in the circuit
|
|
* @return True if all parameters were succesfully set
|
|
*/
|
|
virtual bool setParams(const NamedList& params);
|
|
|
|
/**
|
|
* Get circuit parameter
|
|
* @param param The parameter to get
|
|
* @param value The value of the parameter
|
|
* @return True on success. False if the parameter doesn't exist
|
|
*/
|
|
virtual bool getParam(const String& param, String& value) const
|
|
{ return false; }
|
|
|
|
/**
|
|
* Get boolean circuit parameter
|
|
* @param param The parameter to get
|
|
* @param defValue The default returned value
|
|
* @return Value from circuit, devValue if the parameter doesn't exist
|
|
*/
|
|
virtual bool getBoolParam(const String& param, bool defValue = false) const
|
|
{ return defValue; }
|
|
|
|
/**
|
|
* Get integer circuit parameter
|
|
* @param param The parameter to get
|
|
* @param defValue The default returned value
|
|
* @return Value from circuit, devValue if the parameter doesn't exist
|
|
*/
|
|
virtual int getIntParam(const String& param, int defValue = 0) const
|
|
{ return defValue; }
|
|
|
|
/**
|
|
* Get circuit parameters
|
|
* @param params Parameter list to fill from the circuit
|
|
* @param category Optional category used to select desired parameters
|
|
* @return True if handled
|
|
*/
|
|
virtual bool getParams(NamedList& params, const String& category = String::empty())
|
|
{ return false; }
|
|
|
|
/**
|
|
* Get the group of circuits this one belongs to
|
|
* @return Pointer to circuit group
|
|
*/
|
|
inline SignallingCircuitGroup* group()
|
|
{ return m_group; }
|
|
|
|
/**
|
|
* Get the circuit span this one belongs to
|
|
* @return Pointer to circuit span
|
|
*/
|
|
inline SignallingCircuitSpan* span()
|
|
{ return m_span; }
|
|
|
|
/**
|
|
* Get the group of circuits this one belongs to - const version
|
|
* @return Pointer to const circuit group
|
|
*/
|
|
inline const SignallingCircuitGroup* group() const
|
|
{ return m_group; }
|
|
|
|
/**
|
|
* Get the circuit span this one belongs to - const version
|
|
* @return Pointer to const circuit span
|
|
*/
|
|
inline const SignallingCircuitSpan* span() const
|
|
{ return m_span; }
|
|
|
|
/**
|
|
* Get the group-local code of this circuit
|
|
* @return Identification code within group
|
|
*/
|
|
inline unsigned int code() const
|
|
{ return m_code; }
|
|
|
|
/**
|
|
* Get the available status of the circuit
|
|
* @return True if the circuit is available for use
|
|
*/
|
|
inline bool available() const
|
|
{ return m_status == Idle; }
|
|
|
|
/**
|
|
* Get the connected status of the circuit
|
|
* @return True if the circuit is connected (in use)
|
|
*/
|
|
inline bool connected() const
|
|
{ return m_status == Connected; }
|
|
|
|
/**
|
|
* Reserve this circuit for later use
|
|
* @return True if the circuit was changed from Idle to Reserved
|
|
*/
|
|
inline bool reserve()
|
|
{ return available() && status(Reserved,true); }
|
|
|
|
/**
|
|
* Connect this circuit
|
|
* @param format Optional data format to update for both directions
|
|
* @return True if the circuit state was changed to Connected
|
|
*/
|
|
inline bool connect(const char* format = 0)
|
|
{ updateFormat(format,0); return status(Connected,true); }
|
|
|
|
/**
|
|
* Disconnect (set state to Reserved) this circuit if connected
|
|
* @return True if the circuit was changed from Connected to Reserved
|
|
*/
|
|
inline bool disconnect()
|
|
{ return status() == Connected && status(Reserved,true); }
|
|
|
|
/**
|
|
* Disable this circuit for maintenance
|
|
* @return True if the circuit was changed from Idle to Reserved
|
|
*/
|
|
inline bool disable()
|
|
{ return status(Disabled,true); }
|
|
|
|
/**
|
|
* Set/reset HW failure lock flag
|
|
* @param set True to set, false to reset the flag
|
|
* @param remote True to use remote side of the circuit, false to use the local one
|
|
* @param changed Set/reset changed flag. If false the changed flag won't be affected
|
|
* @param setChanged The value of the changed flag. gnored if changed is false
|
|
* @return True if the flag's state changed
|
|
*/
|
|
bool hwLock(bool set, bool remote, bool changed = false, bool setChanged = false);
|
|
|
|
/**
|
|
* Set/reset maintenance lock flag
|
|
* @param set True to set, false to reset the flag
|
|
* @param remote True to use remote side of the circuit, false to use the local one
|
|
* @param changed Set/reset changed flag. If false the changed flag won't be affected
|
|
* @param setChanged The value of the changed flag. gnored if changed is false
|
|
* @return True if the flag's state changed
|
|
*/
|
|
bool maintLock(bool set, bool remote, bool changed = false, bool setChanged = false);
|
|
|
|
/**
|
|
* Add an event to the queue
|
|
* This method is thread safe
|
|
* @param event The event to enqueue
|
|
*/
|
|
void addEvent(SignallingCircuitEvent* event);
|
|
|
|
/**
|
|
* Get an event from queue
|
|
* This method is thread safe
|
|
* @param when The current time
|
|
* @return SignallingCircuitEvent pointer or 0 if no events
|
|
*/
|
|
SignallingCircuitEvent* getEvent(const Time& when);
|
|
|
|
/**
|
|
* Send an event through this circuit
|
|
* @param type The type of the event to send
|
|
* @param params Optional event parameters
|
|
* @return True on success
|
|
*/
|
|
virtual bool sendEvent(SignallingCircuitEvent::Type type, NamedList* params = 0);
|
|
|
|
/**
|
|
* Get the text associated with a circuit type
|
|
* @param type Circuit type used to retrive the text
|
|
* @return Pointer to the string associated with the given circuit type
|
|
*/
|
|
static const char* lookupType(int type);
|
|
|
|
/**
|
|
* Get the text associated with a circuit status
|
|
* @param status Circuit status used to retrive the text
|
|
* @return Pointer to the string associated with the given circuit status
|
|
*/
|
|
static const char* lookupStatus(int status);
|
|
|
|
/**
|
|
* Keep the lock flags names
|
|
*/
|
|
static TokenDict s_lockNames[];
|
|
|
|
protected:
|
|
/**
|
|
* Constructor
|
|
*/
|
|
SignallingCircuit(Type type, unsigned int code, SignallingCircuitGroup* group = 0,
|
|
SignallingCircuitSpan* span = 0);
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
SignallingCircuit(Type type, unsigned int code, Status status,
|
|
SignallingCircuitGroup* group = 0, SignallingCircuitSpan* span = 0);
|
|
|
|
/**
|
|
* Clear event queue
|
|
* This method is thread safe
|
|
*/
|
|
virtual void clearEvents();
|
|
|
|
/**
|
|
* Event termination notification
|
|
* @param event The terminated event
|
|
*/
|
|
void eventTerminated(SignallingCircuitEvent* event);
|
|
|
|
/**
|
|
* Circuit operations mutex
|
|
*/
|
|
Mutex m_mutex;
|
|
|
|
private:
|
|
SignallingCircuitGroup* m_group; // The group owning this circuit
|
|
SignallingCircuitSpan* m_span; // The span this circuit belongs to
|
|
unsigned int m_code; // Circuit id
|
|
Type m_type; // Circuit type (see enumeration)
|
|
Status m_status; // Circuit local status
|
|
int m_lock; // Circuit lock flags
|
|
ObjList m_events; // In-band events
|
|
SignallingCircuitEvent* m_lastEvent; // The last generated event
|
|
};
|
|
|
|
/**
|
|
* Keeps a range (set) of circuits. The circuit codes contained within a range may
|
|
* not be contiguous.
|
|
* See @ref SignallingUtils::parseUIntArray() for the format of the string ranges
|
|
* this object can be built from
|
|
* @short A circuit range (set of circuits)
|
|
*/
|
|
class YSIG_API SignallingCircuitRange : public String
|
|
{
|
|
YCLASS(SignallingCircuitRange,String)
|
|
friend class SignallingCircuitGroup;
|
|
public:
|
|
/**
|
|
* Constructor
|
|
* @param rangeStr String used to build this range
|
|
* @param name Range name
|
|
* @param strategy Strategy used to allocate circuits from this range
|
|
*/
|
|
SignallingCircuitRange(const String& rangeStr, const char* name = 0,
|
|
int strategy = -1);
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~SignallingCircuitRange()
|
|
{ clear(); }
|
|
|
|
/**
|
|
* Get the number of circuits contained by this range
|
|
* @return The number of circuits contained by this range
|
|
*/
|
|
inline unsigned int count() const
|
|
{ return m_count; }
|
|
|
|
/**
|
|
* Get the pointer to the circuit codes array
|
|
* @return Pointer to the circuit codes array or 0
|
|
*/
|
|
inline const unsigned int* range() const
|
|
{ return (const unsigned int*)m_range.data(); }
|
|
|
|
/**
|
|
* Get the pointer to the circuit codes array
|
|
* @return Pointer to the circuit codes array or 0
|
|
*/
|
|
inline void clear()
|
|
{ m_range.clear(); m_count = 0; }
|
|
|
|
/**
|
|
* Indexing operator
|
|
* @param index The index in the array to retreive
|
|
* @return The code at the given index
|
|
*/
|
|
inline unsigned int operator[](unsigned int index)
|
|
{ return range()[index]; }
|
|
|
|
/**
|
|
* Set this range from a string
|
|
* @param rangeStr String used to (re)build this range
|
|
* @return False if the string has invalid format
|
|
*/
|
|
inline bool set(const String& rangeStr)
|
|
{
|
|
clear();
|
|
return add(rangeStr);
|
|
}
|
|
|
|
/**
|
|
* Add codes to this range from a string
|
|
* @param rangeStr String containing the codes to be added to this range
|
|
* @return False if the string has invalid format
|
|
*/
|
|
bool add(const String& rangeStr);
|
|
|
|
/**
|
|
* Add an array of circuit codes to this range
|
|
* @param codes The array to add
|
|
* @param len The array's length
|
|
*/
|
|
void add(unsigned int* codes, unsigned int len);
|
|
|
|
/**
|
|
* Add a circuit code to this range
|
|
* @param code The circuit code to add
|
|
*/
|
|
inline void add(unsigned int code)
|
|
{ add(&code,1); }
|
|
|
|
/**
|
|
* Add a compact range of circuit codes to this range
|
|
* @param first The first circuit code to add
|
|
* @param last Number of last circuit code
|
|
*/
|
|
void add(unsigned int first, unsigned int last);
|
|
|
|
/**
|
|
* Remove a circuit code from this range
|
|
* @param code The circuit code to remove
|
|
*/
|
|
void remove(unsigned int code);
|
|
|
|
/**
|
|
* Check if a circuit code is within this range
|
|
* @param code The circuit code to find
|
|
* @return True if found
|
|
*/
|
|
bool find(unsigned int code);
|
|
|
|
/**
|
|
* Release memory
|
|
*/
|
|
virtual void destruct()
|
|
{
|
|
clear();
|
|
String::destruct();
|
|
}
|
|
|
|
protected:
|
|
void updateLast(); // Update last circuit code
|
|
|
|
DataBlock m_range; // Array containing the circuit codes
|
|
unsigned int m_count; // The number of elements in the array
|
|
unsigned int m_last; // Last (the greater) not used circuit code within this range
|
|
int m_strategy; // Keep the strategy used to allocate circuits from this range
|
|
unsigned int m_used; // Last used circuit code
|
|
};
|
|
|
|
/**
|
|
* Interface to a stateful group of voice/data circuits
|
|
* @short Group of data circuits used by signalling
|
|
*/
|
|
class YSIG_API SignallingCircuitGroup : public SignallingComponent, public Mutex
|
|
{
|
|
YCLASS(SignallingCircuitGroup,SignallingComponent)
|
|
friend class SignallingCircuit;
|
|
friend class SignallingCallControl;
|
|
friend class SS7ISUP;
|
|
friend class ISDNQ931;
|
|
public:
|
|
/**
|
|
* Circuit allocation strategy
|
|
*/
|
|
enum Strategy {
|
|
Other = 0,
|
|
// basic strategies
|
|
Increment = 0x0001, // round-robin, up
|
|
Decrement = 0x0002, // round-robin, down
|
|
Lowest = 0x0003, // pick first available
|
|
Highest = 0x0004, // pick last available
|
|
Random = 0x0005, // pick random circuit
|
|
// even/odd strict select (glare avoidance)
|
|
OnlyEven = 0x1000,
|
|
OnlyOdd = 0x2000,
|
|
// glare avoidance with fallback (to be able to use all circuits)
|
|
Fallback = 0x4000,
|
|
};
|
|
|
|
/**
|
|
* Constructor, creates a group with a specific base code
|
|
* @param base Base of identification codes for this group
|
|
* @param strategy Default strategy used for circuit allocation
|
|
* @param name Name of this component
|
|
*/
|
|
SignallingCircuitGroup(unsigned int base = 0, int strategy = Increment,
|
|
const char* name = "circgroup");
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~SignallingCircuitGroup();
|
|
|
|
/**
|
|
* Get the number of circuits in this group
|
|
* @return The number of circuits owned by this group
|
|
*/
|
|
inline unsigned int count() const
|
|
{ return m_circuits.count(); }
|
|
|
|
/**
|
|
* Get the base of identification codes for this group
|
|
* @return Base of identification codes for this group
|
|
*/
|
|
inline unsigned int base() const
|
|
{ return m_base; }
|
|
|
|
/**
|
|
* Get the maximum of identification codes for this group
|
|
* @return The maximum of identification codes for this group
|
|
*/
|
|
inline unsigned int last() const
|
|
{ return m_range.m_last; }
|
|
|
|
/**
|
|
* Get the circuit allocation strategy
|
|
* @return Strategy flags ORed together
|
|
*/
|
|
inline int strategy() const
|
|
{ return m_range.m_strategy; }
|
|
|
|
/**
|
|
* Set the circuit allocation strategy
|
|
* @param strategy The new circuit allocation strategy
|
|
*/
|
|
inline void setStrategy(int strategy)
|
|
{ Lock lock(this); m_range.m_strategy = strategy; }
|
|
|
|
/**
|
|
* Get the circuit list
|
|
*/
|
|
inline ObjList& circuits()
|
|
{ return m_circuits; }
|
|
|
|
/**
|
|
* Create a comma separated list with this group's circuits
|
|
* @param dest The destination string
|
|
*/
|
|
void getCicList(String& dest);
|
|
|
|
/**
|
|
* Insert a circuit in the group
|
|
* @param circuit Pointer to the circuit to insert
|
|
* @return False if a circuit with the same code already exists
|
|
*/
|
|
bool insert(SignallingCircuit* circuit);
|
|
|
|
/**
|
|
* Remove a circuit from the group
|
|
* @param circuit Pointer to the circuit to remove
|
|
*/
|
|
void remove(SignallingCircuit* circuit);
|
|
|
|
/**
|
|
* Create a circuit span using the factory
|
|
* @param name Name of the span to create
|
|
* @param start Desired start of circuit codes in span
|
|
* @param params Optional parameters for creation of span and circuits
|
|
* @return Pointer to new circuit span or NULL on failure
|
|
*/
|
|
SignallingCircuitSpan* buildSpan(const String& name, unsigned int start = 0, NamedList* params = 0);
|
|
|
|
/**
|
|
* Insert a circuit span in the group
|
|
* @param span Pointer to the circuit span to insert
|
|
* @return False on failure
|
|
*/
|
|
bool insertSpan(SignallingCircuitSpan* span);
|
|
|
|
/**
|
|
* Build and insert a range from circuits belonging to a given span
|
|
* @param span Span to find
|
|
* @param name Range name or 0 to use span's id
|
|
* @param strategy Strategy used to allocate circuits from the new range,
|
|
* -1 to use group's strategy
|
|
*/
|
|
void insertRange(SignallingCircuitSpan* span, const char* name,
|
|
int strategy = -1);
|
|
|
|
/**
|
|
* Build and insert a range contained in a string.
|
|
* See @ref SignallingUtils::parseUIntArray() for the format of the string range
|
|
* @param range String used to build the range
|
|
* @param name Range name
|
|
* @param strategy Strategy used to allocate circuits from the new range,
|
|
* -1 to use group's strategy
|
|
*/
|
|
void insertRange(const String& range, const char* name,
|
|
int strategy = -1);
|
|
|
|
/**
|
|
* Remove a circuit span from the group
|
|
* @param span Pointer to the circuit span to remove
|
|
* @param delCics True to delete signalling circuits associated to the span
|
|
* @param delSpan True to delete the span
|
|
*/
|
|
void removeSpan(SignallingCircuitSpan* span, bool delCics = true, bool delSpan = false);
|
|
|
|
/**
|
|
* Remove signalling circuits associated to the given span
|
|
* @param span Pointer to the circuit span whose circuits will be removed
|
|
*/
|
|
void removeSpanCircuits(SignallingCircuitSpan* span);
|
|
|
|
/**
|
|
* Find a specific circuit by its identification code
|
|
* @param cic Circuit Identification Code
|
|
* @param local Interpret the cic parameter as group-local code
|
|
* @return Pointer to circuit or NULL if not found
|
|
*/
|
|
SignallingCircuit* find(unsigned int cic, bool local = false);
|
|
|
|
/**
|
|
* Find a range of circuits owned by this group
|
|
* @param name The range name to find
|
|
* @return Pointer to circuit range or 0 if not found
|
|
*/
|
|
SignallingCircuitRange* findRange(const char* name);
|
|
|
|
/**
|
|
* Get the status of a circuit
|
|
* @param cic Circuit Identification Code
|
|
* @return Enumerated status of circuit
|
|
*/
|
|
SignallingCircuit::Status status(unsigned int cic);
|
|
|
|
/**
|
|
* Initiate a circuit status transition
|
|
* @param cic Circuit Identification Code
|
|
* @param newStat Desired new status
|
|
* @param sync Synchronous status change requested
|
|
* @return True if status change has been initiated
|
|
*/
|
|
bool status(unsigned int cic, SignallingCircuit::Status newStat, bool sync = false);
|
|
|
|
/**
|
|
* Reserve a circuit for later use
|
|
* @param checkLock Lock flags to check. If the given lock flags are set, reservation will fail
|
|
* @param strategy Strategy used for allocation, use group default if negative
|
|
* @param range Range of circuits to allocate from. 0 to use group default
|
|
* @return Referenced pointer to a reserved circuit or 0 on failure
|
|
*/
|
|
SignallingCircuit* reserve(int checkLock = -1, int strategy = -1,
|
|
SignallingCircuitRange* range = 0);
|
|
|
|
/**
|
|
* Reserve a circuit for later use
|
|
* @param list Comma separated list of circuits
|
|
* @param mandatory The list is mandatory. If false and none of the circuits in
|
|
* the list are available, try to reserve a free one
|
|
* @param checkLock Lock flags to check. If the given lock flags are set, reservation will fail
|
|
* @param strategy Strategy used for allocation if failed to allocate one from
|
|
* the list, use group default if negative
|
|
* @param range Range of circuits to allocate from. 0 to use group default
|
|
* @return Referenced pointer to a reserved circuit or 0 on failure
|
|
*/
|
|
SignallingCircuit* reserve(const String& list, bool mandatory,
|
|
int checkLock = -1, int strategy = -1, SignallingCircuitRange* range = 0);
|
|
|
|
/**
|
|
* Initiate a release of a circuit
|
|
* @param cic Circuit to release
|
|
* @param sync Synchronous release requested
|
|
* @return True if the circuit release was initiated
|
|
*/
|
|
inline bool release(SignallingCircuit* cic, bool sync = false)
|
|
{ return cic && cic->status(SignallingCircuit::Idle,sync); }
|
|
|
|
/**
|
|
* Get the strategy value associated with a given name
|
|
* @param name Strategy name whose value we want to obtain
|
|
* @param def Value to return if not found
|
|
* @return The requested strategy value or the default one
|
|
*/
|
|
static int str2strategy(const char* name, int def = Increment)
|
|
{ return lookup(name,s_strategy,def); }
|
|
|
|
/**
|
|
* Keep the strategy names
|
|
*/
|
|
static TokenDict s_strategy[];
|
|
|
|
protected:
|
|
/**
|
|
* Remove all spans and circuits. Release object
|
|
*/
|
|
virtual void destroyed()
|
|
{
|
|
clearAll();
|
|
SignallingComponent::destroyed();
|
|
}
|
|
|
|
private:
|
|
unsigned int advance(unsigned int n, int strategy, SignallingCircuitRange& range);
|
|
void clearAll();
|
|
|
|
ObjList m_circuits; // The circuits belonging to this group
|
|
ObjList m_spans; // The spans belonging to this group
|
|
ObjList m_ranges; // Additional circuit ranges
|
|
SignallingCircuitRange m_range; // Range containing all circuits belonging to this group
|
|
unsigned int m_base;
|
|
};
|
|
|
|
/**
|
|
* An interface to a span belonging to a circuit group
|
|
* @short A span in a circuit group
|
|
*/
|
|
class YSIG_API SignallingCircuitSpan : public SignallingComponent
|
|
{
|
|
YCLASS(SignallingCircuitSpan,SignallingComponent)
|
|
public:
|
|
/**
|
|
* Destructor. Remove from group's queue
|
|
*/
|
|
virtual ~SignallingCircuitSpan();
|
|
|
|
/**
|
|
* Get the owner of this span
|
|
* @return SignallingCircuitGroup pointer or 0
|
|
*/
|
|
inline SignallingCircuitGroup* group() const
|
|
{ return m_group; }
|
|
|
|
/**
|
|
* Get this span's id
|
|
* @return The id of this span
|
|
*/
|
|
inline const String& id() const
|
|
{ return m_id; }
|
|
|
|
/**
|
|
* Get the increment in circuit numbers caused by this span
|
|
* @return Circuit number increment for this span
|
|
*/
|
|
inline unsigned int increment() const
|
|
{ return m_increment; }
|
|
|
|
protected:
|
|
/**
|
|
* Constructor
|
|
* @param id Optional span id
|
|
* @param group Optional circuit group owning the span's circuits
|
|
*/
|
|
SignallingCircuitSpan(const char* id = 0, SignallingCircuitGroup* group = 0);
|
|
|
|
/**
|
|
* The owner of this span
|
|
*/
|
|
SignallingCircuitGroup* m_group;
|
|
|
|
/**
|
|
* The increment in channel code caused by this span
|
|
*/
|
|
unsigned int m_increment;
|
|
|
|
private:
|
|
String m_id; // Span's id
|
|
};
|
|
|
|
/**
|
|
* An interface to an abstraction of a Layer 1 (hardware HDLC) interface
|
|
* @short Abstract digital signalling interface (hardware access)
|
|
*/
|
|
class YSIG_API SignallingInterface : virtual public SignallingComponent
|
|
{
|
|
YCLASS(SignallingInterface,SignallingComponent)
|
|
friend class SignallingReceiver;
|
|
public:
|
|
/**
|
|
* Interface control operations
|
|
*/
|
|
enum Operation {
|
|
Specific = 0,
|
|
EnableTx = 0x01,
|
|
EnableRx = 0x02,
|
|
Enable = 0x03,
|
|
DisableTx = 0x04,
|
|
DisableRx = 0x08,
|
|
Disable = 0x0c,
|
|
FlushTx = 0x10,
|
|
FlushRx = 0x20,
|
|
Flush = 0x30,
|
|
QueryTx = 0x40,
|
|
QueryRx = 0x80,
|
|
Query = 0xc0
|
|
};
|
|
|
|
/**
|
|
* Interface generated notifications
|
|
*/
|
|
enum Notification {
|
|
LinkUp = 0,
|
|
LinkDown,
|
|
HardwareError,
|
|
TxClockError,
|
|
RxClockError,
|
|
AlignError,
|
|
CksumError,
|
|
TxOversize,
|
|
RxOversize,
|
|
TxOverflow,
|
|
RxOverflow,
|
|
TxUnderrun,
|
|
RxUnderrun,
|
|
};
|
|
|
|
/**
|
|
* Packet types
|
|
*/
|
|
enum PacketType {
|
|
Unknown = 0,
|
|
SS7Fisu,
|
|
SS7Lssu,
|
|
SS7Msu,
|
|
Q921
|
|
};
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
inline SignallingInterface()
|
|
: m_recvMutex(true,"SignallingInterface::recv"), m_receiver(0)
|
|
{ }
|
|
|
|
/**
|
|
* Destructor, stops and detaches the interface
|
|
*/
|
|
virtual ~SignallingInterface();
|
|
|
|
/**
|
|
* Attach a receiver to the interface. Detach from the old one if valid
|
|
* @param receiver Pointer to receiver to attach
|
|
*/
|
|
virtual void attach(SignallingReceiver* receiver);
|
|
|
|
/**
|
|
* Retrive the signalling receiver attached to this interface
|
|
* @return Pointer to attached receiver, NULL if none
|
|
*/
|
|
inline SignallingReceiver* receiver() const
|
|
{ return m_receiver; }
|
|
|
|
/**
|
|
* Execute a control operation. Operations can enable, disable or flush
|
|
* the transmitter, receiver or both. The status (enabled/disabled) can
|
|
* be queried and also interface-specific operations can be executed.
|
|
* @param oper Operation to execute
|
|
* @param params Optional parameters for the operation
|
|
* @return True if the command completed successfully, for query operations
|
|
* also indicates the interface is enabled and operational
|
|
*/
|
|
virtual bool control(Operation oper, NamedList* params = 0);
|
|
|
|
/**
|
|
* Keeps the names associated with the notifications
|
|
*/
|
|
static TokenDict s_notifName[];
|
|
|
|
protected:
|
|
/**
|
|
* Transmit a packet over the hardware interface
|
|
* @param packet Packet data to send
|
|
* @param repeat Continuously send a copy of the packet while no other
|
|
* data is available for transmission
|
|
* @param type Type of the packet to send
|
|
* @return True if the interface accepted the packet
|
|
*/
|
|
virtual bool transmitPacket(const DataBlock& packet, bool repeat, PacketType type) = 0;
|
|
|
|
/**
|
|
* Push a valid received Signalling Packet up the protocol stack.
|
|
* The starting and ending flags and any CRC are not part of the data.
|
|
* @return True if packet was successfully delivered to the receiver
|
|
*/
|
|
bool receivedPacket(const DataBlock& packet);
|
|
|
|
/**
|
|
* Generate a notification event to the attached receiver
|
|
* @param event Notification event to be reported
|
|
* @return True if notification was accepted by the receiver
|
|
*/
|
|
bool notify(Notification event);
|
|
|
|
private:
|
|
Mutex m_recvMutex; // Lock receiver pointer operations
|
|
SignallingReceiver* m_receiver;
|
|
};
|
|
|
|
/**
|
|
* An interface to an abstraction of a Layer 2 packet data receiver
|
|
* @short Abstract Layer 2 packet data receiver
|
|
*/
|
|
class YSIG_API SignallingReceiver : virtual public SignallingComponent
|
|
{
|
|
YCLASS(SignallingReceiver,SignallingComponent)
|
|
friend class SignallingInterface;
|
|
public:
|
|
/**
|
|
* Constructor
|
|
* @param name Name of the component to create
|
|
*/
|
|
SignallingReceiver(const char* name = 0);
|
|
|
|
/**
|
|
* Destructor, stops the interface and detaches from it
|
|
*/
|
|
virtual ~SignallingReceiver();
|
|
|
|
/**
|
|
* Attach a hardware interface to the data link. Detach from the old one if valid
|
|
* @param iface Pointer to interface to attach
|
|
* @return Pointer to old attached interface or NULL
|
|
*/
|
|
virtual SignallingInterface* attach(SignallingInterface* iface);
|
|
|
|
/**
|
|
* Retrive the interface used by this receiver
|
|
* @return Pointer to the attached interface or NULL
|
|
*/
|
|
inline SignallingInterface* iface() const
|
|
{ return m_interface; }
|
|
|
|
/**
|
|
* Execute a control operation on the attached interface.
|
|
* @param oper Operation to execute
|
|
* @param params Optional parameters for the operation
|
|
* @return True if the command completed successfully, for query operations
|
|
* also indicates the interface is enabled and operational
|
|
*/
|
|
bool control(SignallingInterface::Operation oper, NamedList* params = 0);
|
|
|
|
protected:
|
|
/**
|
|
* Send a packet to the attached interface for transmission
|
|
* @param packet Packet data to send
|
|
* @param repeat Continuously send a copy of the packet while no other
|
|
* data is available for transmission
|
|
* @param type Type of the packet to send
|
|
* @return True if the interface accepted the packet
|
|
*/
|
|
bool transmitPacket(const DataBlock& packet, bool repeat,
|
|
SignallingInterface::PacketType type = SignallingInterface::Unknown);
|
|
|
|
/**
|
|
* Process a Signalling Packet received by the interface
|
|
* @return True if message was successfully processed
|
|
*/
|
|
virtual bool receivedPacket(const DataBlock& packet) = 0;
|
|
|
|
/**
|
|
* Process a notification generated by the attached interface
|
|
* @param event Notification event reported by the interface
|
|
* @return True if notification was processed
|
|
*/
|
|
virtual bool notify(SignallingInterface::Notification event);
|
|
|
|
private:
|
|
Mutex m_ifaceMutex; // Lock interface pointer operations
|
|
SignallingInterface* m_interface;
|
|
};
|
|
|
|
|
|
/**
|
|
* This class keeps a description of a parameter flag used to encode/decode flags
|
|
* @short Description of parameter flags
|
|
*/
|
|
struct SignallingFlags
|
|
{
|
|
/**
|
|
* Mask to separate the relevant bits
|
|
*/
|
|
unsigned int mask;
|
|
|
|
/**
|
|
* Actual value to match
|
|
*/
|
|
unsigned int value;
|
|
|
|
/**
|
|
* Name of the flag
|
|
*/
|
|
const char* name;
|
|
};
|
|
|
|
/**
|
|
* Provides data and services for SS7 and ISDN
|
|
* @short Library wide services and data provider
|
|
*/
|
|
class YSIG_API SignallingUtils
|
|
{
|
|
public:
|
|
/**
|
|
* Retreive the dictionary keeping the coding standard flags of ISUP and ISDN parameters as defined in Q.850
|
|
* @return Pointer to the coding standards dictionary
|
|
*/
|
|
static const TokenDict* codings();
|
|
|
|
/**
|
|
* Retreive the dictionary keeping the location flags of ISUP and ISDN parameters as defined in Q.850
|
|
* @return Pointer to the locations dictionary
|
|
*/
|
|
static const TokenDict* locations();
|
|
|
|
/**
|
|
* Retreive a dictionary given by index and coding standard for ISUP and ISDN parameters
|
|
* @param index The desired disctionary:
|
|
* 0: The release causes of ISUP and ISDN calls as defined in Q.850.
|
|
* 1: The formats negotiated in ISDN and ISUP parameters as defined in Q.931/Q.763.
|
|
* 2: The transfer capability negotiated in ISDN and ISUP parameters as defined in Q.931/Q.763.
|
|
* 3: The transfer mode negotiated in ISDN and ISUP parameters as defined in Q.931/Q.763.
|
|
* 4: The transfer rate negotiated in ISDN and ISUP parameters as defined in Q.931/Q.763.
|
|
* @param coding Optional coding standard. Defaults to CCITT if 0
|
|
* @return Pointer to the requested dictionary or 0
|
|
*/
|
|
static inline const TokenDict* dict(unsigned int index, unsigned char coding = 0)
|
|
{
|
|
if (index > 4)
|
|
return 0;
|
|
return (!coding ? s_dictCCITT[index] : 0);
|
|
}
|
|
|
|
/**
|
|
* Check if a list's parameter (comma separated list of flags) has a given flag
|
|
* @param list The parameter list
|
|
* @param param The parameter to check
|
|
* @param flag The flag to check
|
|
* @return True if the given flag is found
|
|
*/
|
|
static bool hasFlag(const NamedList& list, const char* param, const char* flag);
|
|
|
|
/**
|
|
* Remove a flag from a comma separated list of flags
|
|
* @param flags The list of flags
|
|
* @param flag The flag to remove
|
|
* @return True if the given flag was found and removed
|
|
*/
|
|
static bool removeFlag(String& flags, const char* flag);
|
|
|
|
/**
|
|
* Add string (keyword) if found in a dictionary or integer parameter to a named list
|
|
* @param list Destination list
|
|
* @param param Parameter to add to the list
|
|
* @param tokens The dictionary used to find the given value
|
|
* @param val The value to find/add to the list
|
|
*/
|
|
static void addKeyword(NamedList& list, const char* param,
|
|
const TokenDict* tokens, unsigned int val);
|
|
|
|
/**
|
|
* Dump a buffer to a list of parameters
|
|
* @param comp Signalling component requesting the service. Used to print debug messages
|
|
* @param list The destination list
|
|
* @param param Parameter to add to the list
|
|
* @param buf The buffer containing the data to dump
|
|
* @param len Buffer's length
|
|
* @param sep The separator between elements
|
|
*/
|
|
static void dumpData(const SignallingComponent* comp, NamedList& list, const char* param,
|
|
const unsigned char* buf, unsigned int len, char sep = ' ');
|
|
|
|
/**
|
|
* Dump data from a buffer to a list of parameters. The buffer is parsed until (and including)
|
|
* the first byte with the extension bit (the most significant one) set
|
|
* @param comp Signalling component requesting the service. Used to print debug messages
|
|
* @param list The destination list
|
|
* @param param Parameter to add to the list
|
|
* @param buf The buffer containing the data to dump
|
|
* @param len Buffer's length
|
|
* @param sep The separator between elements
|
|
* @return The number of bytes processed. 0 if the end of the buffer was reached without finding
|
|
* a byte with the extension bit set
|
|
*/
|
|
static unsigned int dumpDataExt(const SignallingComponent* comp, NamedList& list, const char* param,
|
|
const unsigned char* buf, unsigned int len, char sep = ' ');
|
|
|
|
/**
|
|
* Decode a received buffer to a comma separated list of flags and add it to a list of parameters
|
|
* @param comp Signalling component requesting the service. Used to print debug messages
|
|
* @param list The destination list
|
|
* @param param The parameter to add to the list
|
|
* @param flags The flags description to use
|
|
* @param buf The buffer containing the data to parse
|
|
* @param len Buffer's length
|
|
* @return False if the flags description or the buffer is missing or the buffer's length exceeds
|
|
* the length of the 'unsigned int' data type
|
|
*/
|
|
static bool decodeFlags(const SignallingComponent* comp, NamedList& list, const char* param,
|
|
const SignallingFlags* flags, const unsigned char* buf, unsigned int len);
|
|
|
|
/**
|
|
* Decode cause parameters as defined in Q.850
|
|
* @param comp Signalling component requesting the service. Used to print debug messages
|
|
* @param list The destination list
|
|
* @param buf The buffer containing the data to parse
|
|
* @param len Buffer's length
|
|
* @param prefix The prefix to add to the fields before adding to the destination list
|
|
* @param isup True if the requestor is ISUP, false for ISDN requestor
|
|
* @return True if successfully parsed
|
|
*/
|
|
static bool decodeCause(const SignallingComponent* comp, NamedList& list, const unsigned char* buf,
|
|
unsigned int len, const char* prefix, bool isup);
|
|
|
|
/**
|
|
* Decode bearer capabilities as defined in Q.931 (Bearer Capabilities) and Q.763 (User Service Information)
|
|
* @param comp Signalling component requesting the service. Used to print debug messages
|
|
* @param list The destination list
|
|
* @param buf The buffer containing the data to parse
|
|
* @param len Buffer's length
|
|
* @param prefix The prefix to add to the fields before adding to the destination list
|
|
* @param isup True if the requestor is ISUP, false for ISDN requestor
|
|
* @return True if successfully parsed
|
|
*/
|
|
static bool decodeCaps(const SignallingComponent* comp, NamedList& list, const unsigned char* buf,
|
|
unsigned int len, const char* prefix, bool isup);
|
|
|
|
/**
|
|
* Encode a comma separated list of flags. Flags can be prefixed with the '-'
|
|
* character to be reset if previously set
|
|
* @param comp Signalling component requesting the service. Used to print debug messages
|
|
* @param dest Destination flak mask
|
|
* @param flags The flag list
|
|
* @param dict Dictionary used to retrive the flag names and values
|
|
* @return The OR'd value of found flags
|
|
*/
|
|
static void encodeFlags(const SignallingComponent* comp, int& dest, const String& flags,
|
|
TokenDict* dict);
|
|
|
|
/**
|
|
* Encode cause parameters as defined in Q.850. Create with normal clearing value if parameter is missing.
|
|
* Don't encode diagnostic if total length exceeds 32 bytes for Q.931 requestor
|
|
* @param comp Signalling component requesting the service. Used to print debug messages
|
|
* @param buf The destination buffer
|
|
* @param params The list with the parameters
|
|
* @param prefix The prefix of the fields obtained from parameter list
|
|
* @param isup True if the requestor is ISUP, false for ISDN requestor
|
|
* @param fail Fail if the buffer is too long. Ignored if isup is true
|
|
* @return False if the requestor is Q.931, fail is true and the length exceeds 32 bytes
|
|
*/
|
|
static bool encodeCause(const SignallingComponent* comp, DataBlock& buf, const NamedList& params,
|
|
const char* prefix, bool isup, bool fail = false);
|
|
|
|
/**
|
|
* Encode bearer capabilities as defined in Q.931 (Bearer Capabilities) and Q.763 (User Service Information)
|
|
* @param comp Signalling component requesting the service. Used to print debug messages
|
|
* @param buf The destination buffer
|
|
* @param params The list with the parameters
|
|
* @param prefix The prefix of the fields obtained from parameter list
|
|
* @param isup True if the requestor is ISUP, false for ISDN requestor
|
|
* @return True
|
|
*/
|
|
static bool encodeCaps(const SignallingComponent* comp, DataBlock& buf, const NamedList& params,
|
|
const char* prefix, bool isup);
|
|
|
|
/**
|
|
* Parse a list of unsigned integers or unsigned integer intervals. Source elements
|
|
* must be separated by a '.' or ',' character. Interval margins must be separated
|
|
* by a '-' character. Empty elements are ignored
|
|
* @param source The string to parse
|
|
* @param minVal The minimum value for each element in the array
|
|
* @param maxVal The maximum value for each element in the array
|
|
* @param count On exit will contain the length of the returned array (0 on failure)
|
|
* @param discardDup True to discard duplicate values
|
|
* @return Pointer to an array of unsigned integers on success (the caller must delete it after use).
|
|
* 0 on failure (source is empty or has invalid format or an invalid value was found)
|
|
*/
|
|
static unsigned int* parseUIntArray(const String& source, unsigned int minVal, unsigned int maxVal,
|
|
unsigned int& count, bool discardDup);
|
|
|
|
private:
|
|
static TokenDict* s_dictCCITT[5];
|
|
};
|
|
|
|
/**
|
|
* This class is used to manage an analog line and keep data associated with it.
|
|
* Also it can be used to monitor a pair of FXS/FXO analog lines
|
|
* @short An analog line
|
|
*/
|
|
class YSIG_API AnalogLine : public RefObject, public Mutex
|
|
{
|
|
YCLASS(AnalogLine,RefObject)
|
|
friend class AnalogLineGroup; // Reset group if destroyed before the line
|
|
public:
|
|
/**
|
|
* Line type enumerator
|
|
*/
|
|
enum Type {
|
|
FXO, // Telephone linked to an exchange
|
|
FXS, // Telephone exchange linked to a telephone
|
|
Recorder, // Passive FXO recording a 2 wire line
|
|
Monitor, // Monitor (a pair of FXS/FXO lines)
|
|
Unknown
|
|
};
|
|
|
|
/**
|
|
* Line state enumeration
|
|
*/
|
|
enum State {
|
|
OutOfService = -1, // Line is out of service
|
|
Idle = 0, // Line is idle (on hook)
|
|
Dialing = 1, // FXS line is waiting for the FXO to dial the number
|
|
DialComplete = 2, // FXS line: got enough digits from the FXO to reach a destination
|
|
Ringing = 3, // Line is ringing
|
|
Answered = 4, // Line is answered
|
|
CallEnded = 5, // FXS line: notify the FXO on call termination
|
|
OutOfOrder = 6, // FXS line: notify the FXO that the hook is off after call ended notification
|
|
};
|
|
|
|
/**
|
|
* Call setup (such as Caller ID) management (send and detect)
|
|
*/
|
|
enum CallSetupInfo {
|
|
After, // Send/detect call setup after the first ring
|
|
Before, // Send/detect call setup before the first ring
|
|
NoCallSetup // No call setup detect or send
|
|
};
|
|
|
|
/**
|
|
* Constructor. Reserve the line's circuit. Connect it if requested. Creation will fail if no group,
|
|
* circuit, caller or the circuit is already allocated for another line in the group
|
|
* @param grp The group owning this analog line
|
|
* @param cic The code of the signalling circuit used this line
|
|
* @param params The line's parameters
|
|
*/
|
|
AnalogLine(AnalogLineGroup* grp, unsigned int cic, const NamedList& params);
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~AnalogLine();
|
|
|
|
/**
|
|
* Get this line's type
|
|
* @return The line type as enumeration
|
|
*/
|
|
inline Type type() const
|
|
{ return m_type; }
|
|
|
|
/**
|
|
* Get the line state
|
|
* @return The line state as enumeration
|
|
*/
|
|
inline State state() const
|
|
{ return m_state; }
|
|
|
|
/**
|
|
* Get the group owning this line
|
|
* @return The group owning this line
|
|
*/
|
|
inline AnalogLineGroup* group()
|
|
{ return m_group; }
|
|
|
|
/**
|
|
* Get this line's peer if belongs to a pair of monitored lines
|
|
* @return This line's peer if belongs to a pair of monitored lines
|
|
*/
|
|
inline AnalogLine* getPeer()
|
|
{ return m_peer; }
|
|
|
|
/**
|
|
* Remove old peer's peer. Set this line's peer
|
|
* @param line This line's peer
|
|
* @param sync True to synchronize (set/reset) with the old peer
|
|
*/
|
|
void setPeer(AnalogLine* line = 0, bool sync = true);
|
|
|
|
/**
|
|
* Get the line's circuit
|
|
* @return SignallingCircuit pointer or 0 if no circuit was attached to this line
|
|
*/
|
|
inline SignallingCircuit* circuit()
|
|
{ return m_circuit; }
|
|
|
|
/**
|
|
* Get the line address: group_name/circuit_number
|
|
* @return The line address
|
|
*/
|
|
inline const char* address() const
|
|
{ return m_address; }
|
|
|
|
/**
|
|
* Check if allowed to send outband DTMFs (DTMF events)
|
|
* @return True if allowed to send outband DTMFs
|
|
*/
|
|
inline bool outbandDtmf() const
|
|
{ return !m_inband; }
|
|
|
|
/**
|
|
* Check if the line should be answered on polarity change
|
|
* @return True if the line should be answered on polarity change
|
|
*/
|
|
inline bool answerOnPolarity() const
|
|
{ return m_answerOnPolarity; }
|
|
|
|
/**
|
|
* Check if the line should be hanged up on polarity change
|
|
* @return True if the line should be hanged up on polarity change
|
|
*/
|
|
inline bool hangupOnPolarity() const
|
|
{ return m_hangupOnPolarity; }
|
|
|
|
/**
|
|
* Check if the line polarity change should be used
|
|
* @return True if the line polarity change should be used
|
|
*/
|
|
inline bool polarityControl() const
|
|
{ return m_polarityControl; }
|
|
|
|
/**
|
|
* Check if the line is processing (send/receive) the setup info (such as caller id) and when it does it
|
|
* @return Call setup info processing as enumeration
|
|
*/
|
|
inline CallSetupInfo callSetup() const
|
|
{ return m_callSetup; }
|
|
|
|
/**
|
|
* Get the time allowed to ellapse between the call setup data and the first ring
|
|
* @return The time allowed to ellapse between the call setup data and the first ring
|
|
*/
|
|
inline u_int64_t callSetupTimeout() const
|
|
{ return m_callSetupTimeout; }
|
|
|
|
/**
|
|
* Get the time allowed to ellapse without receiving a ring on incoming calls
|
|
* @return The time allowed to ellapse without receiving a ring on incoming calls
|
|
*/
|
|
inline u_int64_t noRingTimeout() const
|
|
{ return m_noRingTimeout; }
|
|
|
|
/**
|
|
* Get the time allowed to stay in alarm. This option can be used by the clients to terminate an active call
|
|
* @return The time allowed to stay in alarm
|
|
*/
|
|
inline u_int64_t alarmTimeout() const
|
|
{ return m_alarmTimeout; }
|
|
|
|
/**
|
|
* Get the time delay of dialing the called number
|
|
* @return The time delay of dialing the called number
|
|
*/
|
|
inline u_int64_t delayDial() const
|
|
{ return m_delayDial; }
|
|
|
|
/**
|
|
* Set/reset accept pulse digits flag
|
|
* @param ok True to accept incoming pulse digits, false to ignore them
|
|
*/
|
|
inline void acceptPulseDigit(bool ok)
|
|
{ m_acceptPulseDigit = ok; }
|
|
|
|
/**
|
|
* Get the private user data of this line
|
|
* @return The private user data of this line
|
|
*/
|
|
inline void* userdata() const
|
|
{ return m_private; }
|
|
|
|
/**
|
|
* Set the private user data of this line and its peer if any
|
|
* @param data The new private user data value of this line
|
|
* @param sync True to synchronize (set data) with the peer
|
|
*/
|
|
inline void userdata(void* data, bool sync = true)
|
|
{
|
|
Lock lock(this);
|
|
m_private = data;
|
|
if (sync && m_peer)
|
|
m_peer->userdata(data,false);
|
|
}
|
|
|
|
/**
|
|
* Get this line's address
|
|
* @return This line's address
|
|
*/
|
|
virtual const String& toString() const
|
|
{ return m_address; }
|
|
|
|
/**
|
|
* Reset the line circuit's echo canceller to line default echo canceller state
|
|
* @param train Start echo canceller training if enabled
|
|
*/
|
|
void resetEcho(bool train);
|
|
|
|
/**
|
|
* Reset the line's circuit (change its state to Reserved)
|
|
* @return True if the line's circuit state was changed to Reserved
|
|
*/
|
|
inline bool resetCircuit()
|
|
{ return state() != OutOfService && m_circuit && m_circuit->reserve(); }
|
|
|
|
/**
|
|
* Set a parameter of this line's circuit
|
|
* @param param Parameter name
|
|
* @param value Optional parameter value
|
|
* @return True if the line's circuit parameter was set
|
|
*/
|
|
inline bool setCircuitParam(const char* param, const char* value = 0)
|
|
{ return m_circuit && m_circuit->setParam(param,value); }
|
|
|
|
/**
|
|
* Connect the line's circuit. Reset line echo canceller
|
|
* @param sync True to synchronize (connect) the peer
|
|
* @return True if the line's circuit state was changed to Connected
|
|
*/
|
|
bool connect(bool sync);
|
|
|
|
/**
|
|
* Disconnect the line's circuit. Reset line echo canceller
|
|
* @param sync True to synchronize (disconnect) the peer
|
|
* @return True if the line's circuit was disconnected (changed state from Connected to Reserved)
|
|
*/
|
|
bool disconnect(bool sync);
|
|
|
|
/**
|
|
* Send an event through this line if not out of service
|
|
* @param type The type of the event to send
|
|
* @param params Optional event parameters
|
|
* @return True on success
|
|
*/
|
|
bool sendEvent(SignallingCircuitEvent::Type type, NamedList* params = 0);
|
|
|
|
/**
|
|
* Send an event through this line if not out of service and change its state on success
|
|
* @param type The type of the event to send
|
|
* @param newState The new state of the line if the event was sent
|
|
* @param params Optional event parameters
|
|
* @return True on success
|
|
*/
|
|
inline bool sendEvent(SignallingCircuitEvent::Type type, State newState,
|
|
NamedList* params = 0)
|
|
{
|
|
if (!sendEvent(type,params))
|
|
return false;
|
|
changeState(newState,false);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Get events from the line's circuit if not out of service. Check timeouts
|
|
* @param when The current time
|
|
* @return AnalogLineEvent pointer or 0 if no events
|
|
*/
|
|
virtual AnalogLineEvent* getEvent(const Time& when);
|
|
|
|
/**
|
|
* Alternate get events from this line or peer
|
|
* @param when The current time
|
|
* @return AnalogLineEvent pointer or 0 if no events
|
|
*/
|
|
virtual AnalogLineEvent* getMonitorEvent(const Time& when);
|
|
|
|
/**
|
|
* Check timeouts if the line is not out of service and no event was generated by the circuit
|
|
* @param when Time to use as computing base for timeouts
|
|
*/
|
|
virtual void checkTimeouts(const Time& when)
|
|
{ }
|
|
|
|
/**
|
|
* Change the line state if neither current or new state are OutOfService
|
|
* @param newState The new state of the line
|
|
* @param sync True to synchronize (change state) the peer
|
|
* @return True if line state changed
|
|
*/
|
|
bool changeState(State newState, bool sync = false);
|
|
|
|
/**
|
|
* Enable/disable line. Change circuit's state to Disabled/Reserved when
|
|
* entering/exiting the OutOfService state
|
|
* @param ok Enable (change state to Idle) or disable (change state to OutOfService) the line
|
|
* @param sync True to synchronize (enable/disable) the peer
|
|
* @param connectNow Connect the line if enabled. Ignored if the line will be disabled
|
|
* @return True if line state changed
|
|
*/
|
|
bool enable(bool ok, bool sync, bool connectNow = true);
|
|
|
|
/**
|
|
* Line type names dictionary
|
|
*/
|
|
static const TokenDict* typeNames();
|
|
|
|
/**
|
|
* Line state names dictionary
|
|
*/
|
|
static const TokenDict* stateNames();
|
|
|
|
/**
|
|
* Call setup info names
|
|
*/
|
|
static const TokenDict* csNames();
|
|
|
|
protected:
|
|
/**
|
|
* Deref the circuit. Remove itself from group
|
|
*/
|
|
virtual void destroyed();
|
|
|
|
private:
|
|
Type m_type; // Line type
|
|
State m_state; // Line state
|
|
bool m_inband; // Refuse to send DTMFs if they should be sent in band
|
|
int m_echocancel; // Default echo canceller state (0: managed by the circuit, -1: off, 1: on)
|
|
bool m_acceptPulseDigit; // Accept incoming pulse digits
|
|
bool m_answerOnPolarity; // Answer on line polarity change
|
|
bool m_hangupOnPolarity; // Hangup on line polarity change
|
|
bool m_polarityControl; // Set line polarity flag
|
|
CallSetupInfo m_callSetup; // Call setup management
|
|
u_int64_t m_callSetupTimeout; // FXO: timeout period for received call setup data before first ring
|
|
u_int64_t m_noRingTimeout; // FXO: timeout period with no ring received on incoming calls
|
|
u_int64_t m_alarmTimeout; // Timeout period to stay in alarms
|
|
u_int64_t m_delayDial; // FXO: Time to delay sending number
|
|
AnalogLineGroup* m_group; // The group owning this line
|
|
SignallingCircuit* m_circuit; // The circuit managed by this line
|
|
String m_address; // Line address: group and circuit
|
|
void* m_private; // Private data used by this line's user
|
|
// Monitor data
|
|
AnalogLine* m_peer; // This line's peer if any
|
|
bool m_getPeerEvent; // Flag used to get events from peer
|
|
};
|
|
|
|
/**
|
|
* An object holding an event generated by an analog line and related references
|
|
* @short A single analog line related event
|
|
*/
|
|
class YSIG_API AnalogLineEvent : public GenObject
|
|
{
|
|
public:
|
|
/**
|
|
* Constructor
|
|
* @param line The analog line that generated this event
|
|
* @param event The signalling circuit event
|
|
*/
|
|
AnalogLineEvent(AnalogLine* line, SignallingCircuitEvent* event)
|
|
: m_line(0), m_event(event)
|
|
{ if (line && line->ref()) m_line = line; }
|
|
|
|
/**
|
|
* Destructor, dereferences any resources
|
|
*/
|
|
virtual ~AnalogLineEvent()
|
|
{
|
|
TelEngine::destruct(m_line);
|
|
TelEngine::destruct(m_event);
|
|
}
|
|
|
|
/**
|
|
* Get the analog line that generated this event
|
|
* @return The analog line that generated this event
|
|
*/
|
|
inline AnalogLine* line()
|
|
{ return m_line; }
|
|
|
|
/**
|
|
* Get the signalling circuit event carried by this analog line event
|
|
* @return The signalling circuit event carried by this analog line event
|
|
*/
|
|
inline SignallingCircuitEvent* event()
|
|
{ return m_event; }
|
|
|
|
/**
|
|
* Disposes the memory
|
|
*/
|
|
virtual void destruct()
|
|
{
|
|
TelEngine::destruct(m_line);
|
|
TelEngine::destruct(m_event);
|
|
GenObject::destruct();
|
|
}
|
|
|
|
private:
|
|
AnalogLine* m_line;
|
|
SignallingCircuitEvent* m_event;
|
|
};
|
|
|
|
/**
|
|
* This class is an analog line container.
|
|
* It may contain another group when used to monitor analog lines
|
|
* @short A group of analog lines
|
|
*/
|
|
class YSIG_API AnalogLineGroup : public SignallingCircuitGroup
|
|
{
|
|
YCLASS(AnalogLineGroup,SignallingCircuitGroup)
|
|
public:
|
|
/**
|
|
* Constructor. Construct an analog line group owning single lines
|
|
* @param type Line type as enumeration
|
|
* @param name Name of this component
|
|
* @param slave True if this is an FXO group owned by an FXS one. Ignored if type is not FXO
|
|
*/
|
|
AnalogLineGroup(AnalogLine::Type type, const char* name, bool slave = false);
|
|
|
|
/**
|
|
* Constructor. Construct an FXS analog line group owning another group of FXO analog lines.
|
|
* The fxo group is owned by this component and will be destructed if invalid (not FXO type)
|
|
* @param name Name of this component
|
|
* @param fxo The FXO group
|
|
*/
|
|
AnalogLineGroup(const char* name, AnalogLineGroup* fxo);
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~AnalogLineGroup();
|
|
|
|
/**
|
|
* Get this group's type
|
|
* @return The group's type
|
|
*/
|
|
inline AnalogLine::Type type() const
|
|
{ return m_type; }
|
|
|
|
/**
|
|
* Get the analog lines belonging to this group
|
|
* @return The group's lines list
|
|
*/
|
|
inline ObjList& lines()
|
|
{ return m_lines; }
|
|
|
|
/**
|
|
* Get the group holding the FXO lines if present
|
|
* @return The group holding the FXO lines or 0
|
|
*/
|
|
inline AnalogLineGroup* fxo()
|
|
{ return m_fxo; }
|
|
|
|
/**
|
|
* Check if this is an FXO group owned by an FXS one
|
|
* @return True if this is an FXO group owned by an FXS one
|
|
*/
|
|
inline bool slave()
|
|
{ return m_slave; }
|
|
|
|
/**
|
|
* Append a line to this group. Line must have the same type as this group and must be owned by this group
|
|
* @param line The line to append
|
|
* @param destructOnFail Destroy line if failed to append. Defaults to true
|
|
* @return True on success
|
|
*/
|
|
bool appendLine(AnalogLine* line, bool destructOnFail = true);
|
|
|
|
/**
|
|
* Remove a line from the list and destruct it
|
|
* @param cic The signalling circuit's code used by the line
|
|
*/
|
|
void removeLine(unsigned int cic);
|
|
|
|
/**
|
|
* Remove a line from the list without destroying it
|
|
* @param line The line to be removed
|
|
*/
|
|
void removeLine(AnalogLine* line);
|
|
|
|
/**
|
|
* Find a line by its circuit
|
|
* @param cic The signalling circuit's code used by the line
|
|
* @return AnalogLine pointer or 0 if not found
|
|
*/
|
|
AnalogLine* findLine(unsigned int cic);
|
|
|
|
/**
|
|
* Find a line by its address
|
|
* @param address The address of the line
|
|
* @return AnalogLine pointer or 0 if not found
|
|
*/
|
|
AnalogLine* findLine(const String& address);
|
|
|
|
/**
|
|
* Iterate through the line list to get an event
|
|
* @param when The current time
|
|
* @return AnalogLineEvent pointer or 0 if no events
|
|
*/
|
|
virtual AnalogLineEvent* getEvent(const Time& when);
|
|
|
|
protected:
|
|
/**
|
|
* Remove all lines. Release object
|
|
*/
|
|
virtual void destroyed();
|
|
|
|
/**
|
|
* The analog lines belonging to this group
|
|
*/
|
|
ObjList m_lines;
|
|
|
|
private:
|
|
AnalogLine::Type m_type; // Line type
|
|
AnalogLineGroup* m_fxo; // The group containing the FXO lines if this is a monitor
|
|
bool m_slave; // True if this is an FXO group owned by an FXS one
|
|
};
|
|
|
|
/**
|
|
* An universal SS7 Layer 3 routing Code Point
|
|
* @short SS7 Code Point
|
|
*/
|
|
class YSIG_API SS7PointCode : public GenObject
|
|
{
|
|
public:
|
|
/**
|
|
* Different incompatible types of points codes
|
|
*/
|
|
enum Type {
|
|
Other = 0,
|
|
ITU = 1, // ITU-T Q.704
|
|
ANSI = 2, // ANSI T1.111.4
|
|
ANSI8 = 3, // 8-bit SLS
|
|
China = 4, // GF 001-9001
|
|
Japan = 5, // JT-Q704, NTT-Q704
|
|
Japan5 = 6, // 5-bit SLS
|
|
// Do not change the next line, must be past last defined type
|
|
DefinedTypes
|
|
};
|
|
|
|
/**
|
|
* Constructor from components
|
|
* @param network ANSI Network Identifier / ITU-T Zone Identification
|
|
* @param cluster ANSI Network Cluster / ITU-T Area/Network Identification
|
|
* @param member ANSI Cluster Member / ITU-T Signalling Point Identification
|
|
*/
|
|
inline SS7PointCode(unsigned char network = 0, unsigned char cluster = 0, unsigned char member = 0)
|
|
: m_network(network), m_cluster(cluster), m_member(member)
|
|
{ }
|
|
|
|
/**
|
|
* Constructor from unpacked format
|
|
* @param type Type of the unpacking desired
|
|
* @param packed Packed format of the point code
|
|
*/
|
|
inline SS7PointCode(Type type, unsigned int packed)
|
|
: m_network(0), m_cluster(0), m_member(0)
|
|
{ unpack(type,packed); }
|
|
|
|
/**
|
|
* Copy constructor
|
|
* @param original Code point to be copied
|
|
*/
|
|
inline SS7PointCode(const SS7PointCode& original)
|
|
: m_network(original.network()), m_cluster(original.cluster()), m_member(original.member())
|
|
{ }
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
inline ~SS7PointCode()
|
|
{ }
|
|
|
|
/**
|
|
* Retrive the Network / Zone component of the Code Point
|
|
* @return ANSI Network Identifier / ITU-T Zone Identification
|
|
*/
|
|
inline unsigned char network() const
|
|
{ return m_network; }
|
|
|
|
/**
|
|
* Retrive the Cluster / Area component of the Code Point
|
|
* @return ANSI Network Cluster / ITU-T Area/Network Identification
|
|
*/
|
|
inline unsigned char cluster() const
|
|
{ return m_cluster; }
|
|
|
|
/**
|
|
* Retrive the Cluster / Point component of the Code Point
|
|
* @return ANSI Cluster Member / ITU-T Signalling Point Identification
|
|
*/
|
|
inline unsigned char member() const
|
|
{ return m_member; }
|
|
|
|
/**
|
|
* Assignment from components
|
|
* @param network ANSI Network Identifier / ITU-T Zone Identification
|
|
* @param cluster ANSI Network Cluster / ITU-T Area/Network Identification
|
|
* @param member ANSI Cluster Member / ITU-T Signalling Point Identification
|
|
*/
|
|
inline void assign(unsigned char network, unsigned char cluster, unsigned char member)
|
|
{ m_network = network; m_cluster = cluster; m_member = member; }
|
|
|
|
/**
|
|
* Assign data members from a given string of form 'network-cluster-member'
|
|
* @param src Source string
|
|
* @param type Type of the point code if numeric (packed) representation is used
|
|
* @return False if the string has incorrect format or individual elements are not in the range 0..255
|
|
*/
|
|
bool assign(const String& src, Type type = Other);
|
|
|
|
/**
|
|
* Assign data members from a packed memory block
|
|
* @param type Type of the point code in memory
|
|
* @param src Pointer to packed point code in memory
|
|
* @param len Length of data, negative to not check validity
|
|
* @param spare Pointer to variable to save spare bits, NULL to ignore them
|
|
* @return True if success, false if invalid type or memory area
|
|
*/
|
|
bool assign(Type type, const unsigned char* src, int len = -1, unsigned char* spare = 0);
|
|
|
|
/**
|
|
* Assignment operator
|
|
* @param original Code point to be copied
|
|
*/
|
|
inline SS7PointCode& operator=(const SS7PointCode& original)
|
|
{ assign(original.network(),original.cluster(),original.member()); return *this; }
|
|
|
|
/**
|
|
* Equality operator
|
|
* @param original Code point to be compared with
|
|
*/
|
|
inline bool operator==(const SS7PointCode& original) const
|
|
{ return m_network == original.network() && m_cluster == original.cluster() && m_member == original.member(); }
|
|
|
|
/**
|
|
* Check if the point code is compatible with a packing type
|
|
* @return True if the Network and Member fit in the packing format
|
|
*/
|
|
bool compatible(Type type) const;
|
|
|
|
/**
|
|
* Pack the code point into a single integer number.
|
|
* @param type Type of the packing desired
|
|
* @return Compact code point as integer or zero if the packing type is not supported
|
|
*/
|
|
unsigned int pack(Type type) const;
|
|
|
|
/**
|
|
* Unpack an integer number into a point code
|
|
* @param type Type of the unpacking desired
|
|
* @param packed Packed format of the point code
|
|
* @return True if the unpacking succeeded and the point code was updated
|
|
*/
|
|
bool unpack(Type type, unsigned int packed);
|
|
|
|
/**
|
|
* Store the point code in a memory area
|
|
* @param type Type of the packing desired
|
|
* @param dest Location to store the label info, must be at least length() long
|
|
* @param spare Spare bits to store after the point code if applicable (ITU)
|
|
* @return True if the unpacking succeeded and the memory was updated
|
|
*/
|
|
bool store(Type type, unsigned char* dest, unsigned char spare = 0) const;
|
|
|
|
/**
|
|
* Get the size (in bits) of a packed code point according to its type
|
|
* @param type Type of the packing
|
|
* @return Number of bits required to represent the code point, zero if unknown
|
|
*/
|
|
static unsigned char size(Type type);
|
|
|
|
/**
|
|
* Get the length (in octets) of a packed code point according to its type
|
|
* @param type Type of the packing
|
|
* @return Number of octets required to represent the code point, zero if unknown
|
|
*/
|
|
static unsigned char length(Type type);
|
|
|
|
/**
|
|
* Get a point type associated to a given text
|
|
* @param text Text to find
|
|
* @return Point code type as enumeration
|
|
*/
|
|
static Type lookup(const char* text)
|
|
{ return (Type)TelEngine::lookup(text,s_names,(int)Other); }
|
|
|
|
/**
|
|
* Get the text associated to a point type
|
|
* @param type Type to find
|
|
* @return The requested text or 0 if not found
|
|
*/
|
|
static const char* lookup(Type type)
|
|
{ return TelEngine::lookup((int)type,s_names); }
|
|
|
|
private:
|
|
static TokenDict s_names[]; // Keep the strigns associated with point code type
|
|
unsigned char m_network;
|
|
unsigned char m_cluster;
|
|
unsigned char m_member;
|
|
};
|
|
|
|
// The number of valid point code types
|
|
#define YSS7_PCTYPE_COUNT (SS7PointCode::DefinedTypes-1)
|
|
|
|
/**
|
|
* Operator to write a point code to a string
|
|
* @param str String to append to
|
|
* @param cp Point code to append to the string
|
|
*/
|
|
YSIG_API String& operator<<(String& str, const SS7PointCode& cp);
|
|
|
|
/**
|
|
* A SS7 Layer 3 routing label, both ANSI and ITU capable
|
|
* @short SS7 Routing Label
|
|
*/
|
|
class YSIG_API SS7Label
|
|
{
|
|
public:
|
|
/**
|
|
* Constructor of an empty, invalid label
|
|
*/
|
|
SS7Label();
|
|
|
|
/**
|
|
* Copy constructor
|
|
* @param original Label to copy
|
|
*/
|
|
SS7Label(const SS7Label& original);
|
|
|
|
/**
|
|
* Swapping constructor, puts SPC into DPC and the other way around
|
|
* @param original Label to swap
|
|
* @param sls Signalling Link Selection
|
|
* @param spare Spare bits
|
|
*/
|
|
SS7Label(const SS7Label& original, unsigned char sls, unsigned char spare = 0);
|
|
|
|
/**
|
|
* Constructor from label components
|
|
* @param type Type of point code used to pack the label
|
|
* @param dpc Destination Point Code
|
|
* @param opc Originating Point Code
|
|
* @param sls Signalling Link Selection
|
|
* @param spare Spare bits
|
|
*/
|
|
SS7Label(SS7PointCode::Type type, const SS7PointCode& dpc,
|
|
const SS7PointCode& opc, unsigned char sls, unsigned char spare = 0);
|
|
|
|
/**
|
|
* Constructor from packed label components
|
|
* @param type Type of point code used to pack the label
|
|
* @param dpc Destination Point Code
|
|
* @param opc Originating Point Code
|
|
* @param sls Signalling Link Selection
|
|
* @param spare Spare bits
|
|
*/
|
|
SS7Label(SS7PointCode::Type type, unsigned int dpc,
|
|
unsigned int opc, unsigned char sls, unsigned char spare = 0);
|
|
|
|
/**
|
|
* Constructor from type and received MSU
|
|
* @param type Type of point code to use to decode the MSU
|
|
* @param msu A received MSU to be parsed
|
|
*/
|
|
SS7Label(SS7PointCode::Type type, const SS7MSU& msu);
|
|
|
|
/**
|
|
* Assignment from label components
|
|
* @param type Type of point code used to pack the label
|
|
* @param dpc Destination Point Code
|
|
* @param opc Originating Point Code
|
|
* @param sls Signalling Link Selection
|
|
* @param spare Spare bits
|
|
*/
|
|
void assign(SS7PointCode::Type type, const SS7PointCode& dpc,
|
|
const SS7PointCode& opc, unsigned char sls, unsigned char spare = 0);
|
|
|
|
/**
|
|
* Assignment from packed label components
|
|
* @param type Type of point code used to pack the label
|
|
* @param dpc Destination Point Code
|
|
* @param opc Originating Point Code
|
|
* @param sls Signalling Link Selection
|
|
* @param spare Spare bits
|
|
*/
|
|
void assign(SS7PointCode::Type type, unsigned int dpc,
|
|
unsigned int opc, unsigned char sls, unsigned char spare = 0);
|
|
|
|
/**
|
|
* Assignment from type and received MSU
|
|
* @param type Type of point code to use to decode the MSU
|
|
* @param msu A received MSU to be parsed
|
|
* @return True if the assignment succeeded
|
|
*/
|
|
bool assign(SS7PointCode::Type type, const SS7MSU& msu);
|
|
|
|
/**
|
|
* Assignment from a packed memory block
|
|
* @param type Type of the point codes in memory block
|
|
* @param src Pointer to packed label in memory
|
|
* @param len Length of data, negative to not check validity
|
|
* @return True if success, false if invalid type or memory area
|
|
*/
|
|
bool assign(SS7PointCode::Type type, const unsigned char* src, int len = -1);
|
|
|
|
/**
|
|
* Pack and store the label in a memory location
|
|
* @param dest Location to store the label info, must be at least length() long
|
|
* @return True on success, false if type is invalid
|
|
*/
|
|
bool store(unsigned char* dest) const;
|
|
|
|
/**
|
|
* Check if the label is compatible with another packing type
|
|
* @return True if the DLC, SLC and SLS fit in the new packing format
|
|
*/
|
|
bool compatible(SS7PointCode::Type type) const;
|
|
|
|
/**
|
|
* Get the type (SS7 dialect) of the routing label
|
|
* @return Dialect of the routing label as enumeration
|
|
*/
|
|
inline SS7PointCode::Type type() const
|
|
{ return m_type; }
|
|
|
|
/**
|
|
* Get the Destination Code Point inside the label
|
|
* @return Reference of the destination code point
|
|
*/
|
|
inline const SS7PointCode& dpc() const
|
|
{ return m_dpc; }
|
|
|
|
/**
|
|
* Get a writable reference to the Destination Code Point inside the label
|
|
* @return Reference of the destination code point
|
|
*/
|
|
inline SS7PointCode& dpc()
|
|
{ return m_dpc; }
|
|
|
|
/**
|
|
* Get the Originating Code Point inside the label
|
|
* @return Reference of the source code point
|
|
*/
|
|
inline const SS7PointCode& opc() const
|
|
{ return m_opc; }
|
|
|
|
/**
|
|
* Get a writable reference to the Originating Code Point inside the label
|
|
* @return Reference of the originating code point
|
|
*/
|
|
inline SS7PointCode& opc()
|
|
{ return m_opc; }
|
|
|
|
/**
|
|
* Get the Signalling Link Selection inside the label
|
|
* @return Value of the SLS field
|
|
*/
|
|
inline unsigned char sls() const
|
|
{ return m_sls; }
|
|
|
|
/**
|
|
* Set the Signalling Link Selection inside the label
|
|
* @param sls New value of the SLS/SLC field
|
|
*/
|
|
inline void setSls(unsigned char sls)
|
|
{ m_sls = sls; }
|
|
|
|
/**
|
|
* Get the spare bits inside the label
|
|
* @return Value of the bits not included in DPC, OPC, or SLS
|
|
*/
|
|
inline unsigned char spare() const
|
|
{ return m_spare; }
|
|
|
|
/**
|
|
* Set the spare bits inside the label
|
|
* @param spare New value of the spare bits
|
|
*/
|
|
inline void setSpare(unsigned char spare)
|
|
{ m_spare = spare; }
|
|
|
|
/**
|
|
* Get the length (in bytes) of this routing label
|
|
* @return Number of bytes required to represent the label, zero if unknown
|
|
*/
|
|
inline unsigned int length() const
|
|
{ return length(m_type); }
|
|
|
|
/**
|
|
* Get the length (in bytes) of a packed routing label according to its type
|
|
* @param type Type of the packing
|
|
* @return Number of bytes required to represent the label, zero if unknown
|
|
*/
|
|
static unsigned int length(SS7PointCode::Type type);
|
|
|
|
/**
|
|
* Get the size (in bits) of this routing label except the spare bits
|
|
* @return Number of bits required to represent this label, zero if unknown
|
|
*/
|
|
inline unsigned char size() const
|
|
{ return size(m_type); }
|
|
|
|
/**
|
|
* Get the size (in bits) of a packed routing label according to its type
|
|
* @param type Type of the packing
|
|
* @return Number of bits required to represent the label, zero if unknown
|
|
*/
|
|
static unsigned char size(SS7PointCode::Type type);
|
|
|
|
private:
|
|
SS7PointCode::Type m_type;
|
|
SS7PointCode m_dpc;
|
|
SS7PointCode m_opc;
|
|
unsigned char m_sls;
|
|
unsigned char m_spare;
|
|
};
|
|
|
|
/**
|
|
* Operator to write a routing label to a string
|
|
* @param str String to append to
|
|
* @param label Label to append to the string
|
|
*/
|
|
YSIG_API String& operator<<(String& str, const SS7Label& label);
|
|
|
|
/**
|
|
* A raw data block with a little more understanding about MSU format
|
|
* @short A block of data that holds a Message Signal Unit
|
|
*/
|
|
class YSIG_API SS7MSU : public DataBlock
|
|
{
|
|
YCLASS(SS7MSU,DataBlock)
|
|
public:
|
|
/**
|
|
* Service indicator values
|
|
*/
|
|
enum Services {
|
|
// Signalling Network Management
|
|
SNM = 0,
|
|
// Maintenance
|
|
MTN = 1,
|
|
// Maintenance special
|
|
MTNS = 2,
|
|
// Signalling Connection Control Part
|
|
SCCP = 3,
|
|
// Telephone User Part
|
|
TUP = 4,
|
|
// ISDN User Part
|
|
ISUP = 5,
|
|
// Data User Part - call and circuit related
|
|
DUP_C = 6,
|
|
// Data User Part - facility messages
|
|
DUP_F = 7,
|
|
// MTP Testing User Part (reserved)
|
|
MTP_T = 8,
|
|
// Broadband ISDN User Part
|
|
BISUP = 9,
|
|
// Satellite ISDN User Part
|
|
SISUP = 10,
|
|
// AAL type2 Signaling
|
|
AAL2 = 12,
|
|
// Bearer Independent Call Control
|
|
BICC = 13,
|
|
// Gateway Control Protocol
|
|
GCP = 14,
|
|
};
|
|
|
|
/**
|
|
* Priority values
|
|
*/
|
|
enum Priority {
|
|
Regular = 0x00,
|
|
Special = 0x10,
|
|
Circuit = 0x20,
|
|
Facility = 0x30
|
|
};
|
|
|
|
/**
|
|
* Subservice types
|
|
*/
|
|
enum NetIndicator {
|
|
International = 0x00,
|
|
SpareInternational = 0x40,
|
|
National = 0x80,
|
|
ReservedNational = 0xc0
|
|
};
|
|
|
|
/**
|
|
* Empty MSU constructor
|
|
*/
|
|
inline SS7MSU()
|
|
{ }
|
|
|
|
/**
|
|
* Copy constructor
|
|
* @param value Original MSU
|
|
*/
|
|
inline SS7MSU(const SS7MSU& value)
|
|
: DataBlock(value)
|
|
{ }
|
|
|
|
/**
|
|
* Constructor from data block
|
|
* @param value Raw data block to copy
|
|
*/
|
|
inline SS7MSU(const DataBlock& value)
|
|
: DataBlock(value)
|
|
{ }
|
|
|
|
/**
|
|
* Constructor of an initialized MSU
|
|
* @param value Data to assign, may be NULL to fill with zeros
|
|
* @param len Length of data, may be zero (then value is ignored)
|
|
* @param copyData True to make a copy of the data, false to use the pointer
|
|
*/
|
|
inline SS7MSU(void* value, unsigned int len, bool copyData = true)
|
|
: DataBlock(value,len,copyData)
|
|
{ }
|
|
|
|
/**
|
|
* Constructor from routing label and raw data
|
|
* @param sio Service Information Octet
|
|
* @param label Routing label
|
|
* @param len Length of data, may be zero (then value is ignored)
|
|
* @param value Data to assign, may be NULL to fill with zeros
|
|
*/
|
|
SS7MSU(unsigned char sio, const SS7Label label, void* value = 0, unsigned int len = 0);
|
|
|
|
/**
|
|
* Constructor from routing label and raw data
|
|
* @param sif Service Information Field
|
|
* @param ssf Subservice Field
|
|
* @param label Routing label
|
|
* @param len Length of data, may be zero (then value is ignored)
|
|
* @param value Data to assign, may be NULL to fill with zeros
|
|
*/
|
|
SS7MSU(unsigned char sif, unsigned char ssf, const SS7Label label, void* value = 0, unsigned int len = 0);
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~SS7MSU();
|
|
|
|
/**
|
|
* Assignment operator
|
|
* @param value Original MSU
|
|
* @return A reference to this MSU
|
|
*/
|
|
inline SS7MSU& operator=(const SS7MSU& value)
|
|
{ DataBlock::operator=(value); return *this; }
|
|
|
|
/**
|
|
* Assignment operator from data block
|
|
* @param value Data block to assign
|
|
* @return A reference to this MSU
|
|
*/
|
|
inline SS7MSU& operator=(const DataBlock& value)
|
|
{ DataBlock::operator=(value); return *this; }
|
|
|
|
/**
|
|
* Check if the MSU length appears valid
|
|
* @return True if the MSU length is valid
|
|
*/
|
|
bool valid() const;
|
|
|
|
/**
|
|
* Get a pointer to raw data
|
|
* @param offs Offset in the MSU
|
|
* @param len Minimum length of data requested
|
|
* @return Pointer to data or NULL if invalid offset or length
|
|
*/
|
|
inline unsigned char* getData(unsigned int offs, unsigned int len = 1)
|
|
{ return (offs+len <= length()) ? offs + (unsigned char*)data() : 0; }
|
|
|
|
/**
|
|
* Get a const pointer to raw data
|
|
* @param offs Offset in the MSU
|
|
* @param len Minimum length of data requested
|
|
* @return Pointer to data or NULL if invalid offset or length
|
|
*/
|
|
inline const unsigned char* getData(unsigned int offs, unsigned int len = 1) const
|
|
{ return (offs+len <= length()) ? offs + (const unsigned char*)data() : 0; }
|
|
|
|
/**
|
|
* Get a pointer to raw user part data after a routing label
|
|
* @param label Routing label of the MSU
|
|
* @param len Minimum length of data requested
|
|
* @return Pointer to data or NULL if invalid offset or length
|
|
*/
|
|
inline unsigned char* getData(const SS7Label& label, unsigned int len = 1)
|
|
{ return getData(label.length()+1,len); }
|
|
|
|
/**
|
|
* Get a const pointer to raw user part data after a routing label
|
|
* @param label Routing label of the MSU
|
|
* @param len Minimum length of data requested
|
|
* @return Pointer to data or NULL if invalid offset or length
|
|
*/
|
|
inline const unsigned char* getData(const SS7Label& label, unsigned int len = 1) const
|
|
{ return getData(label.length()+1,len); }
|
|
|
|
/**
|
|
* Retrive the Service Information Octet
|
|
* @return Value of the SIO or -1 if the MSU is empty
|
|
*/
|
|
inline int getSIO() const
|
|
{ return null() ? -1 : *(const unsigned char*)data(); }
|
|
|
|
/**
|
|
* Retrive the Service Information Field
|
|
* @return Value of the SIF or -1 if the MSU is empty
|
|
*/
|
|
inline int getSIF() const
|
|
{ return null() ? -1 : 0x0f & *(const unsigned char*)data(); }
|
|
|
|
/**
|
|
* Retrive the Subservice Field (SSF)
|
|
* @return Value of the subservice or -1 if the MSU is empty
|
|
*/
|
|
inline int getSSF() const
|
|
{ return null() ? -1 : 0xf0 & *(const unsigned char*)data(); }
|
|
|
|
/**
|
|
* Retrive the Priority Field
|
|
* @return Value of the priority or -1 if the MSU is empty
|
|
*/
|
|
inline int getPrio() const
|
|
{ return null() ? -1 : 0x30 & *(const unsigned char*)data(); }
|
|
|
|
/**
|
|
* Retrive the Network Indicator (NI)
|
|
* @return Value of the subservice or -1 if the MSU is empty
|
|
*/
|
|
inline int getNI() const
|
|
{ return null() ? -1 : 0xc0 & *(const unsigned char*)data(); }
|
|
|
|
/**
|
|
* Retrive the name of the Service as decoded from the SIF
|
|
* @return Name of the service, NULL if unknown or invalid MSU
|
|
*/
|
|
const char* getServiceName() const;
|
|
|
|
/**
|
|
* Retrive the name of the Priority as decoded from the SIF
|
|
* @return Name of the priority, NULL if unknown or invalid MSU
|
|
*/
|
|
const char* getPriorityName() const;
|
|
|
|
/**
|
|
* Retrive the name of the Network Indicator as decoded from the SIF
|
|
* @return Name of the network indicator, NULL if unknown or invalid MSU
|
|
*/
|
|
const char* getIndicatorName() const;
|
|
|
|
/**
|
|
* Get the priority associated with a given name
|
|
* @param name Priority name to find
|
|
* @param defVal Default value to return if not found
|
|
* @return The priority value or the given default one if not exists
|
|
*/
|
|
static unsigned char getPriority(const char* name, unsigned char defVal = Regular);
|
|
|
|
/**
|
|
* Get the network indicator associated with a given name
|
|
* @param name Network indicator name to find
|
|
* @param defVal Default value to return if not found
|
|
* @return The network indicator value or the given default one if not exists
|
|
*/
|
|
static unsigned char getNetIndicator(const char* name, unsigned char defVal = National);
|
|
};
|
|
|
|
/**
|
|
* A an abstraction offering connectivity to a SIGTRAN transport
|
|
* @short An abstract SIGTRAN transport layer
|
|
*/
|
|
class YSIG_API SIGTransport : public SignallingComponent
|
|
{
|
|
YCLASS(SIGTransport,SignallingComponent)
|
|
friend class SIGTRAN;
|
|
public:
|
|
/**
|
|
* Type of transport used
|
|
*/
|
|
enum Transport {
|
|
None = 0,
|
|
Sctp,
|
|
// All the following transports are not standard
|
|
Tcp,
|
|
Udp,
|
|
Unix,
|
|
};
|
|
|
|
/**
|
|
* Get the SIGTRAN component attached to this transport
|
|
* @return Pointer to adaptation layer or NULL
|
|
*/
|
|
inline SIGTRAN* sigtran() const
|
|
{ return m_sigtran; }
|
|
|
|
/**
|
|
* Check if the network transport layer is connected
|
|
* @param streamId Identifier of the stream to check if applicable
|
|
* @return True if the transport (and stream if applicable) is connected
|
|
*/
|
|
virtual bool connected(int streamId) const = 0;
|
|
|
|
protected:
|
|
/**
|
|
* Constructor
|
|
* @param name Default empty component name
|
|
*/
|
|
inline SIGTransport(const char* name = 0)
|
|
: SignallingComponent(name), m_sigtran(0)
|
|
{ }
|
|
|
|
/**
|
|
* Attach an user adaptation layer
|
|
* @param sigtran SIGTRAN component to attach, can be NULL
|
|
*/
|
|
void attach(SIGTRAN* sigtran);
|
|
|
|
/**
|
|
* Notification if the attached state changed
|
|
* @param hasUAL True if an User Adaptation Layer is now attached
|
|
*/
|
|
virtual void attached(bool hasUAL) = 0;
|
|
|
|
/**
|
|
* Send a complete message to the adaptation layer for processing
|
|
* @param msgVersion Version of the protocol
|
|
* @param msgClass Class of the message
|
|
* @param msgType Type of the message, depends on the class
|
|
* @param msg Message data, may be empty
|
|
* @param streamId Identifier of the stream the message was received on
|
|
* @return True if the message was handled
|
|
*/
|
|
bool processMSG(unsigned char msgVersion, unsigned char msgClass,
|
|
unsigned char msgType, const DataBlock& msg, int streamId) const;
|
|
|
|
/**
|
|
* Transmit a message to the network
|
|
* @param msgVersion Version of the protocol
|
|
* @param msgClass Class of the message
|
|
* @param msgType Type of the message, depends on the class
|
|
* @param msg Message data, may be empty
|
|
* @param streamId Identifier of the stream to send the data over
|
|
* @return True if the message was transmitted to network
|
|
*/
|
|
virtual bool transmitMSG(unsigned char msgVersion, unsigned char msgClass,
|
|
unsigned char msgType, const DataBlock& msg, int streamId = 0);
|
|
|
|
/**
|
|
* Transmit a prepared message to the network
|
|
* @param header Message header, typically 8 octets
|
|
* @param msg Message data, may be empty
|
|
* @param streamId Identifier of the stream to send the data over
|
|
* @return True if the message was transmitted to network
|
|
*/
|
|
virtual bool transmitMSG(const DataBlock& header, const DataBlock& msg, int streamId = 0) = 0;
|
|
|
|
private:
|
|
SIGTRAN* m_sigtran;
|
|
};
|
|
|
|
/**
|
|
* An interface to a Signalling Transport user adaptation component
|
|
* @short Abstract SIGTRAN user adaptation component
|
|
*/
|
|
class YSIG_API SIGTRAN
|
|
{
|
|
friend class SIGTransport;
|
|
public:
|
|
/**
|
|
* Message classes
|
|
*/
|
|
enum MsgClass {
|
|
// Management (IUA/M2UA/M3UA/SUA)
|
|
MGMT = 0,
|
|
// Transfer (M3UA)
|
|
TRAN = 1,
|
|
// SS7 Signalling Network Management (M3UA/SUA)
|
|
SSNM = 2,
|
|
// ASP State Maintenance (IUA/M2UA/M3UA/SUA)
|
|
ASPSM = 3,
|
|
// ASP Traffic Maintenance (IUA/M2UA/M3UA/SUA)
|
|
ASPTM = 4,
|
|
// Q.921/Q.931 Boundary Primitives Transport (IUA)
|
|
QPTM = 5,
|
|
// MTP2 User Adaptation (M2UA)
|
|
MAUP = 6,
|
|
// Connectionless Messages (SUA)
|
|
CLMSG = 7,
|
|
// Connection-Oriented Messages (SUA)
|
|
COMSG = 8,
|
|
// Routing Key Management (M3UA)
|
|
RKM = 9,
|
|
// Interface Identifier Management (M2UA)
|
|
IIM = 10,
|
|
// M2PA Messages (M2PA)
|
|
M2PA = 11,
|
|
};
|
|
|
|
/**
|
|
* Constructs an uninitialized signalling transport
|
|
*/
|
|
SIGTRAN();
|
|
|
|
/**
|
|
* Destructor, terminates transport layer
|
|
*/
|
|
virtual ~SIGTRAN();
|
|
|
|
/**
|
|
* Attach a transport (connectivity provider)
|
|
* @param trans Transport to attach to this component
|
|
*/
|
|
virtual void attach(SIGTransport* trans);
|
|
|
|
/**
|
|
* Get the transport of this user adaptation component
|
|
* @return Pointer to the transport layer or NULL
|
|
*/
|
|
inline SIGTransport* transport() const
|
|
{ return m_trans; }
|
|
|
|
/**
|
|
* Check if the network transport layer is connected
|
|
* @param streamId Identifier of the stream to check if applicable
|
|
* @return True if the transport (and stream if applicable) is connected
|
|
*/
|
|
bool connected(int streamId = 0) const;
|
|
|
|
/**
|
|
* Message class names dictionary
|
|
* @return Pointer to dictionary of message classes
|
|
*/
|
|
static const TokenDict* classNames();
|
|
|
|
protected:
|
|
/**
|
|
* Process a complete message
|
|
* @param msgVersion Version of the protocol
|
|
* @param msgClass Class of the message
|
|
* @param msgType Type of the message, depends on the class
|
|
* @param msg Message data, may be empty
|
|
* @param streamId Identifier of the stream the message was received on
|
|
* @return True if the message was handled
|
|
*/
|
|
virtual bool processMSG(unsigned char msgVersion, unsigned char msgClass,
|
|
unsigned char msgType, const DataBlock& msg, int streamId) = 0;
|
|
|
|
/**
|
|
* Transmit a message to the network transport layer
|
|
* @param msgVersion Version of the protocol
|
|
* @param msgClass Class of the message
|
|
* @param msgType Type of the message, depends on the class
|
|
* @param msg Message data, may be empty
|
|
* @param streamId Identifier of the stream to send the data over
|
|
* @return True if the message was transmitted to network
|
|
*/
|
|
bool transmitMSG(unsigned char msgVersion, unsigned char msgClass,
|
|
unsigned char msgType, const DataBlock& msg, int streamId = 0) const;
|
|
|
|
private:
|
|
SIGTransport* m_trans;
|
|
mutable Mutex m_transMutex;
|
|
};
|
|
|
|
/**
|
|
* An interface to a SS7 Application Signalling Part user
|
|
* @short Abstract SS7 ASP user interface
|
|
*/
|
|
class YSIG_API ASPUser
|
|
{
|
|
};
|
|
|
|
/**
|
|
* An interface to a SS7 Signalling Connection Control Part
|
|
* @short Abstract SS7 SCCP interface
|
|
*/
|
|
class YSIG_API SCCP
|
|
{
|
|
public:
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~SCCP();
|
|
|
|
/**
|
|
* Attach an user to this SS7 SCCP
|
|
* @param user Pointer to the SCCP user
|
|
*/
|
|
virtual void attach(SCCPUser* user);
|
|
|
|
protected:
|
|
ObjList m_users;
|
|
};
|
|
|
|
/**
|
|
* An interface to a SS7 Signalling Connection Control Part user
|
|
* @short Abstract SS7 SCCP user interface
|
|
*/
|
|
class YSIG_API SCCPUser
|
|
{
|
|
public:
|
|
/**
|
|
* Destructor, detaches from the SCCP implementation
|
|
*/
|
|
virtual ~SCCPUser();
|
|
|
|
/**
|
|
* Attach as user to a SCCP
|
|
* @param sccp Pointer to the SCCP to use
|
|
*/
|
|
virtual void attach(SCCP* sccp);
|
|
|
|
/**
|
|
* Retrive the SCCP to which this component is attached
|
|
* @return Pointer to the attached SCCP or NULL
|
|
*/
|
|
inline SCCP* sccp() const
|
|
{ return m_sccp; }
|
|
|
|
private:
|
|
SCCP* m_sccp;
|
|
};
|
|
|
|
/**
|
|
* An interface to a SS7 Transactional Capabilities Application Part user
|
|
* @short Abstract SS7 TCAP user interface
|
|
*/
|
|
class YSIG_API TCAPUser
|
|
{
|
|
public:
|
|
/**
|
|
* Destructor, detaches from the TCAP implementation
|
|
*/
|
|
virtual ~TCAPUser();
|
|
|
|
/**
|
|
* Attach as user to a SS7 TCAP
|
|
* @param tcap Pointer to the TCAP to use
|
|
*/
|
|
virtual void attach(SS7TCAP* tcap);
|
|
|
|
/**
|
|
* Retrive the TCAP to which this user is attached
|
|
* @return Pointer to a SS7 TCAP interface or NULL
|
|
*/
|
|
inline SS7TCAP* tcap() const
|
|
{ return m_tcap; }
|
|
|
|
private:
|
|
SS7TCAP* m_tcap;
|
|
};
|
|
|
|
/**
|
|
* An user of a Layer 2 (data link) SS7 message transfer part
|
|
* @short Abstract user of SS7 layer 2 (data link) message transfer part
|
|
*/
|
|
class YSIG_API SS7L2User : virtual public SignallingComponent
|
|
{
|
|
YCLASS(SS7L2User,SignallingComponent)
|
|
friend class SS7Layer2;
|
|
public:
|
|
/**
|
|
* Attach a SS7 Layer 2 (data link) to the user component
|
|
* @param link Pointer to data link to attach
|
|
*/
|
|
virtual void attach(SS7Layer2* link) = 0;
|
|
|
|
/**
|
|
* Detach a SS7 Layer 2 (data link) from the user component
|
|
* @param link Pointer to data link to detach
|
|
*/
|
|
virtual void detach(SS7Layer2* link) = 0;
|
|
|
|
protected:
|
|
/**
|
|
* Process a MSU received from the Layer 2 component
|
|
* @param msu Message data, starting with Service Indicator Octet
|
|
* @param link Data link that delivered the MSU
|
|
* @param sls Signalling Link the MSU was received from
|
|
* @return True if the MSU was processed
|
|
*/
|
|
virtual bool receivedMSU(const SS7MSU& msu, SS7Layer2* link, int sls) = 0;
|
|
|
|
/**
|
|
* Process a notification generated by the attached data link
|
|
* @param link Data link that generated the notification
|
|
* @return True if notification was processed
|
|
*/
|
|
virtual void notify(SS7Layer2* link) = 0;
|
|
};
|
|
|
|
/**
|
|
* An interface to a Layer 2 (data link) SS7 message transfer part
|
|
* @short Abstract SS7 layer 2 (data link) message transfer part
|
|
*/
|
|
class YSIG_API SS7Layer2 : virtual public SignallingComponent
|
|
{
|
|
YCLASS(SS7Layer2,SignallingComponent)
|
|
public:
|
|
/**
|
|
* LSSU Status Indications
|
|
*/
|
|
enum LinkStatus {
|
|
OutOfAlignment = 0,
|
|
NormalAlignment = 1,
|
|
EmergencyAlignment = 2,
|
|
OutOfService = 3,
|
|
ProcessorOutage = 4,
|
|
Busy = 5,
|
|
// short versions as defined by RFC
|
|
O = OutOfAlignment,
|
|
N = NormalAlignment,
|
|
E = EmergencyAlignment,
|
|
OS = OutOfService,
|
|
PO = ProcessorOutage,
|
|
B = Busy,
|
|
};
|
|
|
|
/**
|
|
* Control primitives
|
|
*/
|
|
enum Operation {
|
|
// take link out of service
|
|
Pause = 0x100,
|
|
// start link operation, align if it needs to
|
|
Resume = 0x200,
|
|
// start link, force realignment
|
|
Align = 0x300,
|
|
// get operational status
|
|
Status = 0x400,
|
|
};
|
|
|
|
/**
|
|
* Push a Message Signal Unit down the protocol stack
|
|
* @param msu Message data, starting with Service Indicator Octet
|
|
* @return True if message was successfully queued
|
|
*/
|
|
virtual bool transmitMSU(const SS7MSU& msu) = 0;
|
|
|
|
/**
|
|
* Remove the MSUs waiting in the transmit queue and return them
|
|
* @return List of MSUs taken from the queue
|
|
*/
|
|
virtual ObjList* recoverMSU();
|
|
|
|
/**
|
|
* Retrive the current link status indications
|
|
* @return Link status indication bits
|
|
*/
|
|
virtual unsigned int status() const;
|
|
|
|
/**
|
|
* Get the name of a Layer 2 status
|
|
* @param status Status indication value
|
|
* @param brief Request to return the short status name
|
|
* @return String describing the status
|
|
*/
|
|
virtual const char* statusName(unsigned int status, bool brief) const;
|
|
|
|
/**
|
|
* Get the name of the current local Layer 2 status
|
|
* @param brief Request to return the short status name
|
|
* @return String describing the status
|
|
*/
|
|
inline const char* statusName(bool brief = false) const
|
|
{ return statusName(status(),brief); }
|
|
|
|
/**
|
|
* Check if the link is fully operational
|
|
* @return True if the link is aligned and operational
|
|
*/
|
|
virtual bool operational() const = 0;
|
|
|
|
/**
|
|
* Attach a Layer 2 user component to the data link. Detach from the old one if valid
|
|
* @param l2user Pointer to Layer 2 user component to attach
|
|
*/
|
|
void attach(SS7L2User* l2user);
|
|
|
|
/**
|
|
* Get the Layer 2 user component that works with this data link
|
|
* @return Pointer to the user component to which the messages are sent
|
|
*/
|
|
inline SS7L2User* user() const
|
|
{ return m_l2user; }
|
|
|
|
/**
|
|
* Get the Signalling Link Selection number allocated to this link
|
|
* @return SLS value assigned by the upper layer
|
|
*/
|
|
inline int sls() const
|
|
{ return m_sls; }
|
|
|
|
/**
|
|
* Assign a new Signalling Link Selection number
|
|
* @param linkSel New SLS to assign to this link
|
|
*/
|
|
inline void sls(int linkSel)
|
|
{ if ((m_sls < 0) || !m_l2user) m_sls = linkSel; }
|
|
|
|
/**
|
|
* Execute a control operation. Operations can change the link status or
|
|
* can query the aligned status.
|
|
* @param oper Operation to execute
|
|
* @param params Optional parameters for the operation
|
|
* @return True if the command completed successfully, for query operations
|
|
* also indicates the data link is aligned and operational
|
|
*/
|
|
virtual bool control(Operation oper, NamedList* params = 0);
|
|
|
|
/**
|
|
* Query or modify layer's settings or operational parameters
|
|
* @param params The list of parameters to query or change
|
|
* @return True if the control operation was executed
|
|
*/
|
|
virtual bool control(NamedList& params);
|
|
|
|
protected:
|
|
/**
|
|
* Constructor
|
|
*/
|
|
inline SS7Layer2()
|
|
: m_l2userMutex(true,"SS7Layer2::l2user"), m_l2user(0), m_sls(-1)
|
|
{ }
|
|
|
|
/**
|
|
* Push a received Message Signal Unit up the protocol stack
|
|
* @param msu Message data, starting with Service Indicator Octet
|
|
* @return True if message was successfully delivered to the user component
|
|
*/
|
|
inline bool receivedMSU(const SS7MSU& msu)
|
|
{
|
|
m_l2userMutex.lock();
|
|
RefPointer<SS7L2User> tmp = m_l2user;
|
|
m_l2userMutex.unlock();
|
|
return tmp && tmp->receivedMSU(msu,this,m_sls);
|
|
}
|
|
|
|
/**
|
|
* Notify out user part about a status change
|
|
*/
|
|
inline void notify()
|
|
{
|
|
m_l2userMutex.lock();
|
|
RefPointer<SS7L2User> tmp = m_l2user;
|
|
m_l2userMutex.unlock();
|
|
if (tmp)
|
|
tmp->notify(this);
|
|
}
|
|
|
|
private:
|
|
Mutex m_l2userMutex;
|
|
SS7L2User* m_l2user;
|
|
int m_sls;
|
|
};
|
|
|
|
/**
|
|
* An user of a Layer 3 (data link) SS7 message transfer part
|
|
* @short Abstract user of SS7 layer 3 (network) message transfer part
|
|
*/
|
|
class YSIG_API SS7L3User : virtual public SignallingComponent
|
|
{
|
|
friend class SS7Layer3;
|
|
friend class SS7Router;
|
|
public:
|
|
/**
|
|
* Attach a SS7 Layer 3 (network) to the user component
|
|
* @param network Pointer to network component to attach
|
|
*/
|
|
virtual void attach(SS7Layer3* network) = 0;
|
|
|
|
protected:
|
|
/**
|
|
* Process a MSU received from the Layer 3 component
|
|
* @param msu Message data, starting with Service Indicator Octet
|
|
* @param label Routing label of the received MSU
|
|
* @param network Network layer that delivered the MSU
|
|
* @param sls Signalling Link the MSU was received from
|
|
* @return True if the MSU was processed
|
|
*/
|
|
virtual bool receivedMSU(const SS7MSU& msu, const SS7Label& label, SS7Layer3* network, int sls) = 0;
|
|
|
|
/**
|
|
* Process a notification generated by the attached network layer
|
|
* @param link Network or linkset that generated the notification
|
|
* @param sls Signalling Link that generated the notification, negative if none
|
|
*/
|
|
virtual void notify(SS7Layer3* link, int sls);
|
|
};
|
|
|
|
/**
|
|
* An interface to a Layer 3 (network) SS7 message transfer part
|
|
* @short Abstract SS7 layer 3 (network) message transfer part
|
|
*/
|
|
class YSIG_API SS7Layer3 : virtual public SignallingComponent
|
|
{
|
|
YCLASS(SS7Layer3,SignallingComponent)
|
|
friend class SS7Router; // Access the data members to build the routing table
|
|
public:
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~SS7Layer3()
|
|
{ attach(0); }
|
|
|
|
/**
|
|
* Push a Message Signal Unit down the protocol stack
|
|
* @param msu Message data, starting with Service Indicator Octet
|
|
* @param label Routing label of the MSU to use in routing
|
|
* @param sls Signalling Link Selection, negative to choose best
|
|
* @return Link the message was successfully queued to, negative for error
|
|
*/
|
|
virtual int transmitMSU(const SS7MSU& msu, const SS7Label& label, int sls = -1) = 0;
|
|
|
|
/**
|
|
* Check if the network/linkset is fully operational
|
|
* @param sls Signalling Link to check, negative to check if any is operational
|
|
* @return True if the linkset is enabled and operational
|
|
*/
|
|
virtual bool operational(int sls = -1) const = 0;
|
|
|
|
/**
|
|
* Attach a Layer 3 user component to this network. Detach the old user if valid.
|
|
* Attach itself to the given user
|
|
* @param l3user Pointer to Layer 3 user component to attach
|
|
*/
|
|
void attach(SS7L3User* l3user);
|
|
|
|
/**
|
|
* Retrive the Layer 3 user component to which this network is attached
|
|
* @return Pointer to the Layer 3 user this network is attached to
|
|
*/
|
|
inline SS7L3User* user() const
|
|
{ return m_l3user; }
|
|
|
|
/**
|
|
* Retrive the point code type of this Layer 3 component for a MSU type
|
|
* @param netType Type of the network like coded in the MSU NI field
|
|
* @return The type of codepoint this component will use
|
|
*/
|
|
SS7PointCode::Type type(unsigned char netType) const;
|
|
|
|
/**
|
|
* Set the point code of this Layer 3 component for a network type
|
|
* @param type Point code type to set for the network type
|
|
* @param netType Type of the network like coded in the MSU NI field
|
|
*/
|
|
void setType(SS7PointCode::Type type, unsigned char netType);
|
|
|
|
/**
|
|
* Set the point code of this Layer 3 component for all network types
|
|
* @param type Point code type to set
|
|
*/
|
|
void setType(SS7PointCode::Type type);
|
|
|
|
/**
|
|
* Build the list of outgoing routes serviced by this network. Clear the list before re-building it.
|
|
* This method is thread safe
|
|
* @param params The parameter list
|
|
* @return False if no route available
|
|
*/
|
|
bool buildRoutes(const NamedList& params);
|
|
|
|
/**
|
|
* Get the priority of a route.
|
|
* This method is thread safe
|
|
* @param type Destination point code type
|
|
* @param packedPC The packed point code
|
|
* @return The priority of the route. -1 if no route to the given point code
|
|
*/
|
|
unsigned int getRoutePriority(SS7PointCode::Type type, unsigned int packedPC);
|
|
|
|
/**
|
|
* Print the destinations or routing table to output
|
|
*/
|
|
void printRoutes();
|
|
|
|
protected:
|
|
/**
|
|
* Constructor
|
|
* @param type Default point code type
|
|
*/
|
|
inline SS7Layer3(SS7PointCode::Type type = SS7PointCode::Other)
|
|
: SignallingComponent("SS7Layer3"),
|
|
m_l3userMutex(true,"SS7Layer3::l3user"),
|
|
m_l3user(0),
|
|
m_routeMutex(true,"SS7Layer3::route")
|
|
{ setType(type); }
|
|
|
|
/**
|
|
* Push a received Message Signal Unit up the protocol stack
|
|
* @param msu Message data, starting with Service Indicator Octet
|
|
* @param label Routing label of the received MSU
|
|
* @param sls Signalling Link the MSU was received from
|
|
* @return True if message was successfully delivered to the user component
|
|
*/
|
|
inline bool receivedMSU(const SS7MSU& msu, const SS7Label& label, int sls)
|
|
{
|
|
m_l3userMutex.lock();
|
|
RefPointer<SS7L3User> tmp = m_l3user;
|
|
m_l3userMutex.unlock();
|
|
return tmp && tmp->receivedMSU(msu,label,this,sls);
|
|
}
|
|
|
|
/**
|
|
* Notify out user part about a status change
|
|
* @param sls Signallink Link that generated the notification, -1 if none
|
|
*/
|
|
inline void notify(int sls = -1)
|
|
{
|
|
m_l3userMutex.lock();
|
|
RefPointer<SS7L3User> tmp = m_l3user;
|
|
m_l3userMutex.unlock();
|
|
if (tmp)
|
|
tmp->notify(this,sls);
|
|
}
|
|
|
|
/**
|
|
* Default processing of a MTN (Maintenance MSU)
|
|
* @param msu Message data, starting with Service Indicator Octet
|
|
* @param label Routing label of the received MSU
|
|
* @param sls Signalling Link the MSU was received from
|
|
* @return True if the MSU was processed
|
|
*/
|
|
virtual bool maintenance(const SS7MSU& msu, const SS7Label& label, int sls);
|
|
|
|
/**
|
|
* Default processing of a SNM (Management MSU)
|
|
* @param msu Message data, starting with Service Indicator Octet
|
|
* @param label Routing label of the received MSU
|
|
* @param sls Signalling Link the MSU was received from
|
|
* @return True if the MSU was processed
|
|
*/
|
|
virtual bool management(const SS7MSU& msu, const SS7Label& label, int sls);
|
|
|
|
/**
|
|
* Default processing of an unknown MSU - emit an User Part Unavailable
|
|
* @param msu Message data, starting with Service Indicator Octet
|
|
* @param label Routing label of the received MSU
|
|
* @param sls Signalling Link the MSU was received from
|
|
* @param cause Unavailability cause code (Q.704 15.17.5)
|
|
* @return True if the MSU was processed
|
|
*/
|
|
virtual bool unavailable(const SS7MSU& msu, const SS7Label& label, int sls, unsigned char cause = 0);
|
|
|
|
/**
|
|
* Find a route having the specified point code type and packed point code.
|
|
* This method is thread safe
|
|
* @param type The point code type used to choose the list of packed point codes
|
|
* @param packed The packed point code to find in the list
|
|
* @return SS7Route pointer or 0 if type is invalid or the given packed point code was not found
|
|
*/
|
|
SS7Route* findRoute(SS7PointCode::Type type, unsigned int packed);
|
|
|
|
/**
|
|
* Add a network to the routing table. Clear all its routes before appending it to the table
|
|
* Used by a SS7 router. This method is thread safe
|
|
* @param network The network to add to the routing table
|
|
*/
|
|
void updateRoutes(SS7Layer3* network);
|
|
|
|
/**
|
|
* Remove the given network from all destinations in the routing table.
|
|
* Remove the entry in the routing table if empty (no more routes to the point code).
|
|
* Used by a SS7 router. This method is thread safe
|
|
* @param network The network to remove
|
|
*/
|
|
void removeRoutes(SS7Layer3* network);
|
|
|
|
private:
|
|
Mutex m_l3userMutex; // Mutex to lock L3 user pointer
|
|
SS7L3User* m_l3user;
|
|
SS7PointCode::Type m_cpType[4]; // Map incoming MSUs net indicators to point code type
|
|
Mutex m_routeMutex; // Mutex to lock routing list operations
|
|
ObjList m_route[YSS7_PCTYPE_COUNT]; // Outgoing point codes serviced by a network (for each point code type)
|
|
// or the routing table of a message router
|
|
};
|
|
|
|
/**
|
|
* An interface to a Layer 4 (application) SS7 protocol
|
|
* @short Abstract SS7 layer 4 (application) protocol
|
|
*/
|
|
class YSIG_API SS7Layer4 : public SS7L3User
|
|
{
|
|
public:
|
|
/**
|
|
* Attach a SS7 network or router to this service. Detach itself from the old one if valid
|
|
* @param network Pointer to network or router to attach
|
|
*/
|
|
virtual void attach(SS7Layer3* network);
|
|
|
|
/**
|
|
* Retrive the SS7 network or router to which this service is attached
|
|
* @return Pointer to the network or router this service is attached to
|
|
*/
|
|
inline SS7Layer3* network() const
|
|
{ return m_layer3; }
|
|
|
|
protected:
|
|
/**
|
|
* Constructor
|
|
*/
|
|
SS7Layer4();
|
|
|
|
/**
|
|
* Ask the Layer 3 to push a Message Signal Unit down the protocol stack
|
|
* @param msu Message data, starting with Service Indicator Octet
|
|
* @param label Routing label of the MSU to use in routing
|
|
* @param sls Signalling Link Selection, negative to choose best
|
|
* @return Link the message was successfully queued to, negative for error
|
|
*/
|
|
inline int transmitMSU(const SS7MSU& msu, const SS7Label& label, int sls = -1)
|
|
{
|
|
m_l3Mutex.lock();
|
|
RefPointer<SS7Layer3> tmp = m_layer3;
|
|
m_l3Mutex.unlock();
|
|
return tmp ? tmp->transmitMSU(msu,label,sls) : -1;
|
|
}
|
|
|
|
private:
|
|
Mutex m_l3Mutex; // Lock pointer use operations
|
|
SS7Layer3* m_layer3;
|
|
};
|
|
|
|
/**
|
|
* Keeps a packed destination point code, a network priority or a list of networks used
|
|
* to route to the enclosed destination point code
|
|
* @short A SS7 MSU route
|
|
*/
|
|
class YSIG_API SS7Route : public RefObject, public Mutex
|
|
{
|
|
friend class SS7Layer3;
|
|
public:
|
|
/**
|
|
* Constructor
|
|
* @param packed The packed value of the destination point code
|
|
* @param priority Optional value of the network priority
|
|
*/
|
|
inline SS7Route(unsigned int packed, unsigned int priority = 0)
|
|
: Mutex(true,"SS7Route"),
|
|
m_packed(packed), m_priority(priority), m_changes(0)
|
|
{ m_networks.setDelete(false); }
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~SS7Route()
|
|
{ }
|
|
|
|
/**
|
|
* Attach a network to use for this destination or change its priority.
|
|
* This method is thread safe
|
|
* @param network The network to attach or change priority
|
|
* @param type The point code type used to get the priority from the given network or the networks already in the list
|
|
*/
|
|
void attach(SS7Layer3* network, SS7PointCode::Type type);
|
|
|
|
/**
|
|
* Remove a network from the list without deleting it.
|
|
* This method is thread safe
|
|
* @param network The network to remove
|
|
* @return False if the list of networks is empty
|
|
*/
|
|
bool detach(SS7Layer3* network);
|
|
|
|
/**
|
|
* Try to transmit a MSU through one of the attached networks.
|
|
* This method is thread safe
|
|
* @param router The router requesting the operation (used for debug)
|
|
* @param msu Message data, starting with Service Indicator Octet
|
|
* @param label Routing label of the MSU
|
|
* @param sls Signalling Link Selection, negative to choose best
|
|
* @return Link the message was successfully queued to, negative for error
|
|
*/
|
|
int transmitMSU(const SS7Router* router, const SS7MSU& msu, const SS7Label& label, int sls);
|
|
|
|
private:
|
|
unsigned int m_packed; // Packed destination point code
|
|
unsigned int m_priority; // Network priority for the given destination (used by SS7Layer3)
|
|
ObjList m_networks; // List of networks used to route to the given destination (used by SS7Router)
|
|
int m_changes; // Counter used to spot changes in the list
|
|
};
|
|
|
|
/**
|
|
* A message router between Transfer and Application layers.
|
|
* Messages are distributed according to the service type.
|
|
* @short Main router for SS7 message transfer and applications
|
|
*/
|
|
class YSIG_API SS7Router : public SS7L3User, public SS7Layer3, public Mutex
|
|
{
|
|
YCLASS2(SS7Router,SS7L3User,SS7Layer3)
|
|
public:
|
|
/**
|
|
* Default constructor
|
|
* @param params The list with the parameters
|
|
*/
|
|
SS7Router(const NamedList& params);
|
|
|
|
/**
|
|
* Configure and initialize the router, maintenance and management
|
|
* @param config Optional configuration parameters override
|
|
* @return True if the router was initialized properly
|
|
*/
|
|
virtual bool initialize(const NamedList* config);
|
|
|
|
/**
|
|
* Push a Message Signal Unit down the protocol stack
|
|
* @param msu Message data, starting with Service Indicator Octet
|
|
* @param label Routing label of the MSU to use in routing
|
|
* @param sls Signalling Link Selection, negative to choose best
|
|
* @return Link the message was successfully queued to, negative for error
|
|
*/
|
|
virtual int transmitMSU(const SS7MSU& msu, const SS7Label& label, int sls = -1);
|
|
|
|
/**
|
|
* Check if the router is fully operational
|
|
* @param sls Signalling Link to check, negative to check if any is operational
|
|
* @return True if the router is enabled and operational
|
|
*/
|
|
virtual bool operational(int sls = -1) const;
|
|
|
|
/**
|
|
* Attach a SS7 Layer 3 (network) to the router. Attach the router to the given network
|
|
* @param network Pointer to network to attach
|
|
*/
|
|
virtual void attach(SS7Layer3* network);
|
|
|
|
/**
|
|
* Detach a SS7 Layer 3 (network) from the router. Detach the router from the given network
|
|
* @param network Pointer to network to detach
|
|
*/
|
|
virtual void detach(SS7Layer3* network);
|
|
|
|
/**
|
|
* Attach a SS7 Layer 4 (service) to the router. Attach itself to the service
|
|
* @param service Pointer to service to attach
|
|
*/
|
|
void attach(SS7Layer4* service);
|
|
|
|
/**
|
|
* Detach a SS7 Layer 4 (service) from the router. Detach itself from the service
|
|
* @param service Pointer to service to detach
|
|
*/
|
|
void detach(SS7Layer4* service);
|
|
|
|
protected:
|
|
/**
|
|
* Process a MSU received from the Layer 3 component
|
|
* @param msu Message data, starting with Service Indicator Octet
|
|
* @param label Routing label of the received MSU
|
|
* @param network Network layer that delivered the MSU
|
|
* @param sls Signalling Link the MSU was received from
|
|
* @return True if the MSU was processed
|
|
*/
|
|
virtual bool receivedMSU(const SS7MSU& msu, const SS7Label& label, SS7Layer3* network, int sls);
|
|
|
|
/**
|
|
* Process a notification generated by the attached network layer
|
|
* @param network Network or linkset that generated the notification
|
|
* @param sls Signallink Link that generated the notification, negative if none
|
|
* @return True if notification was processed
|
|
*/
|
|
virtual void notify(SS7Layer3* network, int sls);
|
|
|
|
/** List of L3 (networks) attached to this router */
|
|
ObjList m_layer3;
|
|
/** List of L4 (services) attached to this router */
|
|
ObjList m_layer4;
|
|
/** Counter used to spot changes in the lists of L3 or L4 */
|
|
int m_changes;
|
|
};
|
|
|
|
/**
|
|
* RFC4165 SS7 Layer 2 implementation over SCTP/IP.
|
|
* M2PA is intended to be used as a symmetrical Peer-to-Peer replacement of
|
|
* a hardware based SS7 data link.
|
|
* @short SIGTRAN MTP2 User Peer-to-Peer Adaptation Layer
|
|
*/
|
|
class YSIG_API SS7M2PA : public SS7Layer2, public SIGTRAN
|
|
{
|
|
};
|
|
|
|
/**
|
|
* RFC3331 SS7 Layer 2 implementation over SCTP/IP.
|
|
* M2UA is intended to be used as a Provider-User where real MTP2 runs on a
|
|
* Signalling Gateway and MTP3 runs on an Application Server.
|
|
* @short SIGTRAN MTP2 User Adaptation Layer
|
|
*/
|
|
class YSIG_API SS7M2UA : public SS7Layer2, public SIGTRAN
|
|
{
|
|
};
|
|
|
|
/**
|
|
* RFC3332 SS7 Layer 3 implementation over SCTP/IP.
|
|
* M3UA is intended to be used as a Provider-User where real MTP3 runs on a
|
|
* Signalling Gateway and MTP users are located on an Application Server.
|
|
* @short SIGTRAN MTP3 User Adaptation Layer
|
|
*/
|
|
class YSIG_API SS7M3UA : public SS7Layer3, public SIGTRAN
|
|
{
|
|
};
|
|
|
|
/**
|
|
* Q.703 SS7 Layer 2 (Data Link) implementation on top of a hardware interface
|
|
* @short SS7 Layer 2 implementation on top of a hardware interface
|
|
*/
|
|
class YSIG_API SS7MTP2 : public SS7Layer2, public SignallingReceiver, public SignallingDumpable, public Mutex
|
|
{
|
|
YCLASS2(SS7MTP2,SS7Layer2,SignallingReceiver)
|
|
public:
|
|
/**
|
|
* Types of error correction
|
|
*/
|
|
enum ErrorCorrection {
|
|
Basic, // retransmits only based on sequence numbers
|
|
Preventive, // continuously retransmit unacknowledged packets
|
|
Adaptive, // switch to using preventive retransmission dynamically
|
|
};
|
|
|
|
/**
|
|
* Constructor
|
|
* @param params Layer's parameters
|
|
* @param status Initial status
|
|
*/
|
|
SS7MTP2(const NamedList& params, unsigned int status = OutOfService);
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~SS7MTP2();
|
|
|
|
/**
|
|
* Configure and initialize MTP2 and its interface
|
|
* @param config Optional configuration parameters override
|
|
* @return True if MTP2 and the interface were initialized properly
|
|
*/
|
|
virtual bool initialize(const NamedList* config);
|
|
|
|
/**
|
|
* Push a Message Signal Unit down the protocol stack
|
|
* @param msu MSU data to transmit
|
|
* @return True if message was successfully queued
|
|
*/
|
|
virtual bool transmitMSU(const SS7MSU& msu);
|
|
|
|
/**
|
|
* Remove the MSUs waiting in the transmit queue and return them
|
|
* @return List of MSUs taken from the queue
|
|
*/
|
|
virtual ObjList* recoverMSU();
|
|
|
|
/**
|
|
* Retrive the current link status indications
|
|
* @return Link status indication bits
|
|
*/
|
|
virtual unsigned int status() const;
|
|
|
|
/**
|
|
* Check if the link is aligned.
|
|
* The link may not be operational, the other side may be still proving.
|
|
* @return True if the link is aligned
|
|
*/
|
|
virtual bool aligned() const;
|
|
|
|
/**
|
|
* Check if the link is aligned and operational
|
|
* @return True if the link is operational
|
|
*/
|
|
virtual bool operational() const;
|
|
|
|
/**
|
|
* Execute a control operation. Operations can change the link status or
|
|
* can query the aligned status.
|
|
* @param oper Operation to execute
|
|
* @param params Optional parameters for the operation
|
|
* @return True if the command completed successfully, for query operations
|
|
* also indicates the data link is aligned and operational
|
|
*/
|
|
virtual bool control(Operation oper, NamedList* params = 0);
|
|
|
|
/**
|
|
* Process a notification generated by the attached interface
|
|
* @param event Notification event reported by the interface
|
|
* @return True if notification was processed
|
|
*/
|
|
virtual bool notify(SignallingInterface::Notification event);
|
|
|
|
protected:
|
|
/**
|
|
* Remove all attachements. Disposes the memory
|
|
*/
|
|
virtual void destroyed()
|
|
{
|
|
SS7Layer2::attach(0);
|
|
TelEngine::destruct(SignallingReceiver::attach(0));
|
|
SignallingComponent::destroyed();
|
|
}
|
|
|
|
/**
|
|
* Periodical timer tick used to perform alignment and housekeeping
|
|
* @param when Time to use as computing base for events and timeouts
|
|
*/
|
|
virtual void timerTick(const Time& when);
|
|
|
|
/**
|
|
* Process a Signalling Packet received by the hardware interface
|
|
* @return True if message was successfully processed
|
|
*/
|
|
virtual bool receivedPacket(const DataBlock& packet);
|
|
|
|
/**
|
|
* Process a received Fill-In Signal Unit
|
|
*/
|
|
virtual void processFISU();
|
|
|
|
/**
|
|
* Process a received Link Status Signal Unit
|
|
* @param status Link status indications
|
|
*/
|
|
virtual void processLSSU(unsigned int status);
|
|
|
|
/**
|
|
* Push a Link Status Signal Unit down the protocol stack
|
|
* @param status Link status indications
|
|
* @return True if message was successfully queued
|
|
*/
|
|
bool transmitLSSU(unsigned int status);
|
|
|
|
/**
|
|
* Push a Link Status Signal Unit with the current status down the protocol stack
|
|
* @return True if message was successfully queued
|
|
*/
|
|
inline bool transmitLSSU()
|
|
{ return transmitLSSU(m_lStatus); }
|
|
|
|
/**
|
|
* Push a Fill-In Signal Unit down the protocol stack
|
|
* @return True if message was successfully queued
|
|
*/
|
|
bool transmitFISU();
|
|
|
|
/**
|
|
* Initiates alignment and proving procedure
|
|
* @param emergency True if emergency alignment is desired
|
|
*/
|
|
void startAlignment(bool emergency = false);
|
|
|
|
/**
|
|
* Abort an alignment procedure if link errors occur
|
|
*/
|
|
void abortAlignment();
|
|
|
|
/**
|
|
* Start the link proving period
|
|
* @return True if proving period was started
|
|
*/
|
|
bool startProving();
|
|
|
|
private:
|
|
virtual bool control(NamedList& params)
|
|
{ return SignallingDumpable::control(params,this) || SS7Layer2::control(params); }
|
|
void unqueueAck(unsigned char bsn);
|
|
bool txPacket(const DataBlock& packet, bool repeat, SignallingInterface::PacketType type = SignallingInterface::Unknown);
|
|
void setLocalStatus(unsigned int status);
|
|
void setRemoteStatus(unsigned int status);
|
|
// sent but yet unacknowledged packets
|
|
ObjList m_queue;
|
|
// data link status (alignment) - desired, local and remote
|
|
unsigned int m_status, m_lStatus, m_rStatus;
|
|
// various interval period end
|
|
u_int64_t m_interval;
|
|
// time when resending packets
|
|
u_int64_t m_resend;
|
|
// time when aborting resending packets
|
|
u_int64_t m_abort;
|
|
// time when need to transmit next FISU/LSSU
|
|
u_int64_t m_fillTime;
|
|
// remote congestion indicator
|
|
bool m_congestion;
|
|
// backward and forward sequence numbers
|
|
unsigned char m_bsn, m_fsn;
|
|
// backward and forward indicator bits
|
|
bool m_bib, m_fib;
|
|
// last forward sequence number we sent a retransmission request
|
|
unsigned char m_lastFsn;
|
|
// last received backward sequence number
|
|
unsigned char m_lastBsn;
|
|
// last received backward indicator bit
|
|
bool m_lastBib;
|
|
// count of errors
|
|
int m_errors;
|
|
// packet resend interval
|
|
unsigned int m_resendMs;
|
|
// packet resend abort interval
|
|
unsigned int m_abortMs;
|
|
// FISU/LSSU soft resend interval
|
|
unsigned int m_fillIntervalMs;
|
|
// fill link with end-to-end FISU/LSSU
|
|
bool m_fillLink;
|
|
};
|
|
|
|
/**
|
|
* Q.704 SS7 Layer 3 (Network) implementation on top of SS7 Layer 2
|
|
* @short SS7 Layer 3 implementation on top of Layer 2
|
|
*/
|
|
class YSIG_API SS7MTP3 : public SS7Layer3, public SS7L2User, public SignallingDumpable, public Mutex
|
|
{
|
|
YCLASS(SS7MTP3,SS7Layer3)
|
|
public:
|
|
/**
|
|
* Control primitives
|
|
*/
|
|
enum Operation {
|
|
// take linkset out of service
|
|
Pause = 0x100,
|
|
// start linkset operation
|
|
Resume = 0x200,
|
|
// get operational status
|
|
Status = 0x400,
|
|
};
|
|
|
|
/**
|
|
* Constructor
|
|
* @param params Layer's parameters
|
|
*/
|
|
SS7MTP3(const NamedList& params);
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~SS7MTP3();
|
|
|
|
/**
|
|
* Configure and initialize the MTP3 and all its links
|
|
* @param config Optional configuration parameters override
|
|
* @return True if MTP3 and at least one link were initialized properly
|
|
*/
|
|
virtual bool initialize(const NamedList* config);
|
|
|
|
/**
|
|
* Push a Message Signal Unit down the protocol stack
|
|
* @param msu Message data, starting with Service Indicator Octet
|
|
* @param label Routing label of the MSU used in routing
|
|
* @param sls Signalling Link Selection, negative to choose best
|
|
* @return Link the message was successfully queued to, negative for error
|
|
*/
|
|
virtual int transmitMSU(const SS7MSU& msu, const SS7Label& label, int sls = -1);
|
|
|
|
/**
|
|
* Check if the network/linkset is fully operational
|
|
* @param sls Signalling Link to check, negative to check if any is operational
|
|
* @return True if the linkset is enabled and operational
|
|
*/
|
|
virtual bool operational(int sls = -1) const;
|
|
|
|
/**
|
|
* Execute a control operation on the linkset
|
|
* @param oper Operation to execute
|
|
* @param params Optional parameters for the operation
|
|
* @return True if the command completed successfully, for query operations
|
|
* also indicates the linkset is enabled and operational
|
|
*/
|
|
virtual bool control(Operation oper, NamedList* params = 0);
|
|
|
|
/**
|
|
* Attach a SS7 Layer 2 (data link) to the network transport. Attach itself to the link
|
|
* @param link Pointer to data link to attach
|
|
*/
|
|
virtual void attach(SS7Layer2* link);
|
|
|
|
/**
|
|
* Detach a SS7 Layer 2 (data link) from the network transport. Remove the link's L2 user
|
|
* @param link Pointer to data link to detach
|
|
*/
|
|
virtual void detach(SS7Layer2* link);
|
|
|
|
/**
|
|
* Query or modify layer's settings or operational parameters
|
|
* @param params The list of parameters to query or change
|
|
* @return True if the control operation was executed
|
|
*/
|
|
virtual bool control(NamedList& params);
|
|
|
|
/**
|
|
* Get the total number of links attached
|
|
* @return Number of attached data links
|
|
*/
|
|
inline unsigned int linksTotal() const
|
|
{ return m_total; }
|
|
|
|
/**
|
|
* Get the number of links that are currently operational
|
|
* @return Number of operational data links
|
|
*/
|
|
inline unsigned int linksActive() const
|
|
{ return m_active; }
|
|
|
|
protected:
|
|
/**
|
|
* Detach all links and user. Destroys the object, disposes the memory
|
|
*/
|
|
virtual void destroyed();
|
|
|
|
/**
|
|
* Process a MSU received from the Layer 2 component
|
|
* @param msu Message data, starting with Service Indicator Octet
|
|
* @param link Data link that delivered the MSU
|
|
* @param sls Signalling Link the MSU was received from
|
|
* @return True if the MSU was processed
|
|
*/
|
|
virtual bool receivedMSU(const SS7MSU& msu, SS7Layer2* link, int sls);
|
|
|
|
/**
|
|
* Process a notification generated by the attached data link
|
|
* @param link Data link that generated the notification
|
|
* @return True if notification was processed
|
|
*/
|
|
virtual void notify(SS7Layer2* link);
|
|
|
|
/**
|
|
* Count the total and active number of links
|
|
* @return Number of active links
|
|
*/
|
|
unsigned int countLinks();
|
|
|
|
private:
|
|
ObjList m_links;
|
|
// total links in linkset
|
|
unsigned int m_total;
|
|
// currently active links
|
|
unsigned int m_active;
|
|
// inhibited flag
|
|
bool m_inhibit;
|
|
};
|
|
|
|
/**
|
|
* Decoded Signalling Network Management (SNM) User Part message
|
|
* @short SNM signalling message
|
|
*/
|
|
class YSIG_API SS7MsgSNM : public SignallingMessage
|
|
{
|
|
public:
|
|
/**
|
|
* SNM Message type as defined by Q.704 Table 1
|
|
*/
|
|
enum Type {
|
|
Unknown = 0,
|
|
COO = 0x11, // Changeover Order signal
|
|
ECO = 0x12, // Emergency Changeover Order signal
|
|
RCT = 0x13, // Route Set Congestion Test signal
|
|
TFP = 0x14, // Transfer Prohibited signal
|
|
RST = 0x15, // Route Set Test for prohibited destination
|
|
RSP = RST, // Route Set Test for prohibited destination (ANSI)
|
|
LIN = 0x16, // Link Inhibit signal
|
|
TRA = 0x17, // Traffic Restart Allowed signal
|
|
DLC = 0x18, // Data Link Connection Order signal
|
|
UPU = 0x1a, // User Part Unavailable signal
|
|
COA = 0x21, // Changeover Acknowledgment signal
|
|
ECA = 0x22, // Emergency Changeover Acknowledgment signal
|
|
TFC = 0x23, // Transfer Controlled signal
|
|
TCP = 0x24, // Transfer Cluster Prohibited
|
|
TFPA = TCP, // Transfer Prohibited Acknowledgment (Yellow Book only)
|
|
RSR = 0x25, // Route Set Test for prohibited destination (national use)
|
|
LUN = 0x26, // Link Uninhibit signal
|
|
TRW = 0x27, // Traffic Restart Waiting (ANSI only)
|
|
CSS = 0x28, // Connection Successful signal
|
|
TFR = 0x34, // Transfer Restricted signal (national use)
|
|
RCP = 0x35, // Route Set Test for cluster-prohibited
|
|
LIA = 0x36, // Link Inhibit Acknowledgment signal
|
|
CNS = 0x38, // Connection Not Successful signal
|
|
TCR = 0x44, // Transfer Cluster Restricted signal (ANSI only)
|
|
RCR = 0x45, // Route Set Test for cluster-restricted (ANSI only)
|
|
LUA = 0x46, // Link Uninhibit Acknowledgment signal
|
|
CNP = 0x48, // Connection Not Possible signal
|
|
CBD = 0x51, // Changeback Declaration signal
|
|
TFA = 0x54, // Transfer Allowed signal
|
|
LID = 0x56, // Link Inhibit Denied signal
|
|
CBA = 0x61, // Changeback Acknowledgment signal
|
|
TCA = 0x64, // Transfer Cluster Allowed
|
|
TFAA = TCA, // Transfer Allowed Acknowledgment (Yellow Book only)
|
|
LFU = 0x66, // Link Forced Uninhibit signal
|
|
LLT = 0x76, // Link Local Inhibit Test signal
|
|
LLI = LLT, // Link Local Inhibit Test signal (ANSI)
|
|
LRT = 0x86, // Link Remote Inhibit Test signal
|
|
LRI = LRT, // Link Remote Inhibit Test signal (ANSI)
|
|
};
|
|
|
|
/**
|
|
* SNM Message group (H0) as defined by Q.704 15.3
|
|
*/
|
|
enum Group {
|
|
CHM = 0x01, // Changeover and changeback
|
|
ECM = 0x02, // Emergency changeover
|
|
FCM = 0x03, // Tranfer controlled and signalling route set congestion
|
|
TFM = 0x04, // Tranfer prohibited/allowed/restricted
|
|
RSM = 0x05, // Signalling route/set/test
|
|
MIM = 0x06, // Management inhibit
|
|
TRM = 0x07, // Traffic restart allowed
|
|
DLM = 0x08, // Signalling data/link/connection
|
|
UFC = 0x0a, // User part flow control
|
|
};
|
|
|
|
/**
|
|
* Constructor
|
|
* @param type Message type
|
|
*/
|
|
SS7MsgSNM(unsigned char type);
|
|
|
|
/**
|
|
* Get the type of this message
|
|
* @return The type of this message
|
|
*/
|
|
inline unsigned char type() const
|
|
{ return m_type; }
|
|
|
|
/**
|
|
* Get the group this message belongs to
|
|
* @return This message's group
|
|
*/
|
|
inline unsigned char group() const
|
|
{ return m_type & 0x0f; }
|
|
|
|
/**
|
|
* Fill a string with this message's parameters for debug purposes
|
|
* @param dest The destination string
|
|
* @param label The routing label
|
|
* @param params True to add parameters
|
|
*/
|
|
void toString(String& dest, const SS7Label& label, bool params) const;
|
|
|
|
/**
|
|
* Parse a received buffer and build a message from it
|
|
* @param receiver The SS7 management entity that received the MSU
|
|
* @param type Message type
|
|
* @param pcType The point code type contained in received MSU's label
|
|
* @param buf Buffer after message head
|
|
* @param len Buffer length
|
|
* @return Valid message pointer of 0 on failure
|
|
*/
|
|
static SS7MsgSNM* parse(SS7Management* receiver, unsigned char type,
|
|
SS7PointCode::Type pcType,
|
|
const unsigned char* buf, unsigned int len);
|
|
|
|
/**
|
|
* Get the dictionary containing the names of the message type
|
|
*/
|
|
static const TokenDict* names();
|
|
|
|
/**
|
|
* Convert a SNM message type to a C string
|
|
* @param type Type of SNM message to look up
|
|
* @param defvalue Default string to return
|
|
* @return Name of the SNM message type
|
|
*/
|
|
static inline const char* lookup(Type type, const char* defvalue = 0)
|
|
{ return TelEngine::lookup(type,names(),defvalue); }
|
|
|
|
/**
|
|
* Look up a SNM message name
|
|
* @param name String name of the SNM message
|
|
* @param defvalue Default type to return
|
|
* @return Encoded type of the SNM message
|
|
*/
|
|
static inline Type lookup(const char* name, Type defvalue = Unknown)
|
|
{ return static_cast<Type>(TelEngine::lookup(name,names(),defvalue)); }
|
|
|
|
private:
|
|
unsigned char m_type;
|
|
};
|
|
|
|
/**
|
|
* Decoded Maintenance (MTN) User Part message
|
|
* @short MTN signalling message
|
|
*/
|
|
class YSIG_API SS7MsgMTN
|
|
{
|
|
public:
|
|
/**
|
|
* MTN Message type as defined by Q.707 5.4
|
|
*/
|
|
enum Type {
|
|
Unknown = 0,
|
|
SLTM = 0x11, // Signalling Link Test Message
|
|
SLTA = 0x21, // Signalling Link Test Acknowledgment
|
|
};
|
|
|
|
static const TokenDict* names();
|
|
|
|
/**
|
|
* Convert a MTN message type to a C string
|
|
* @param type Type of MTN message to look up
|
|
* @param defvalue Default string to return
|
|
* @return Name of the MTN message type
|
|
*/
|
|
static inline const char* lookup(Type type, const char* defvalue = 0)
|
|
{ return TelEngine::lookup(type,names(),defvalue); }
|
|
|
|
/**
|
|
* Look up a MTN message name
|
|
* @param name String name of the MTN message
|
|
* @param defvalue Default type to return
|
|
* @return Encoded type of the MTN message
|
|
*/
|
|
static inline Type lookup(const char* name, Type defvalue = Unknown)
|
|
{ return static_cast<Type>(TelEngine::lookup(name,names(),defvalue)); }
|
|
};
|
|
|
|
/**
|
|
* Decoded ISDN User Part message
|
|
* @short ISUP signalling message
|
|
*/
|
|
class YSIG_API SS7MsgISUP : public SignallingMessage
|
|
{
|
|
YCLASS(SS7MsgISUP,SignallingMessage)
|
|
friend class SS7ISUPCall;
|
|
public:
|
|
/**
|
|
* ISUP Message type as defined by Q.762 Table 2 and Q.763 Table 4
|
|
*/
|
|
enum Type {
|
|
Unknown = 0,
|
|
IAM = 0x01, // Initial Address Message
|
|
SAM = 0x02, // Subsequent Address Message
|
|
INR = 0x03, // Information Request (national use)
|
|
INF = 0x04, // Information (national use)
|
|
COT = 0x05, // Continuity
|
|
ACM = 0x06, // Address Complete Message
|
|
CON = 0x07, // Connect
|
|
FOT = 0x08, // Forward Transfer
|
|
ANM = 0x09, // Answer Message
|
|
REL = 0x0c, // Release Request
|
|
SUS = 0x0d, // Suspend
|
|
RES = 0x0e, // Resume
|
|
RLC = 0x10, // Release Complete
|
|
CCR = 0x11, // Continuity Check Request
|
|
RSC = 0x12, // Reset Circuit
|
|
BLK = 0x13, // Blocking
|
|
UBL = 0x14, // Unblocking
|
|
BLA = 0x15, // Blocking Acknowledgement
|
|
UBA = 0x16, // Unblocking Acknowledgement
|
|
GRS = 0x17, // Circuit Group Reset
|
|
CGB = 0x18, // Circuit Group Blocking
|
|
CGU = 0x19, // Circuit Group Unblocking
|
|
CGA = 0x1a, // Circuit Group Blocking Acknowledgement
|
|
CGBA = CGA,
|
|
CUA = 0x1b, // Circuit Group Unblocking Acknowledgement
|
|
CMR = 0x1c, // Call Modification Request (ANSI only)
|
|
CMC = 0x1d, // Call Modification Completed (ANSI only)
|
|
CMRJ = 0x1e, // Call Modification Rejected (ANSI only)
|
|
FACR = 0x1f, // Facility Request
|
|
FAA = 0x20, // Facility Accepted
|
|
FRJ = 0x21, // Facility Reject
|
|
FAD = 0x22, // Facility Deactivated (ANSI only)
|
|
FAI = 0x23, // Facility Information (ANSI only)
|
|
LPA = 0x24, // Loopback Acknowledgement (national use)
|
|
CSVR = 0x25, // CUG Selection and Validation Request (ANSI only)
|
|
CSVS = 0x26, // CUG Selection and Validation Response (ANSI only)
|
|
DRS = 0x27, // Delayed Release (ANSI only)
|
|
PAM = 0x28, // Pass Along Message (national use)
|
|
GRA = 0x29, // Circuit Group Reset Acknowledgement
|
|
CQM = 0x2a, // Circuit Group Query (national use)
|
|
CQR = 0x2b, // Circuit Group Query Response (national use)
|
|
CPR = 0x2c, // Call Progress
|
|
CPG = CPR,
|
|
USR = 0x2d, // User-to-User Information
|
|
UEC = 0x2e, // Unequipped CIC (national use)
|
|
UCIC = UEC,
|
|
CNF = 0x2f, // Confusion
|
|
OLM = 0x30, // Overload Message (national use)
|
|
CRG = 0x31, // Charge Information (national use and format, ITU only)
|
|
NRM = 0x32, // Network Resource Management
|
|
FAC = 0x33, // Facility (national use)
|
|
UPT = 0x34, // User Part Test
|
|
UPA = 0x35, // User Part Available
|
|
IDR = 0x36, // Identification Request (ITU only)
|
|
IRS = 0x37, // Identification Response (ITU only)
|
|
SGM = 0x38, // Segmentation
|
|
LOP = 0x40, // Loop Prevention
|
|
APM = 0x41, // Application Transport
|
|
PRI = 0x42, // Pre-Release Information
|
|
SDN = 0x43, // Subsequent Directory Number (national use)
|
|
CRA = 0xe9, // Circuit Reservation Acknowledgement (ANSI only)
|
|
CRM = 0xea, // Circuit Reservation (ANSI only)
|
|
CVR = 0xeb, // Circuit Validation Response (ANSI only)
|
|
CVT = 0xec, // Circuit Validation Test (ANSI only)
|
|
EXM = 0xed, // Exit Message (ANSI only)
|
|
};
|
|
|
|
/**
|
|
* ISUP Message type as defined by Q.763 Table 5
|
|
*/
|
|
enum Parameters {
|
|
EndOfParameters = 0,
|
|
CallReference = 0x01,
|
|
TransmissionMediumRequirement = 0x02,
|
|
AccessTransport = 0x03,
|
|
CalledPartyNumber = 0x04,
|
|
SubsequentNumber = 0x05,
|
|
NatureOfConnectionIndicators = 0x06,
|
|
ForwardCallIndicators = 0x07,
|
|
OptionalForwardCallIndicators = 0x08,
|
|
CallingPartyCategory = 0x09,
|
|
CallingPartyNumber = 0x0a,
|
|
RedirectingNumber = 0x0b,
|
|
RedirectionNumber = 0x0c,
|
|
ConnectionRequest = 0x0d,
|
|
InformationRequestIndicators = 0x0e,
|
|
InformationIndicators = 0x0f,
|
|
ContinuityIndicators = 0x10,
|
|
BackwardCallIndicators = 0x11,
|
|
CauseIndicators = 0x12,
|
|
RedirectionInformation = 0x13,
|
|
GroupSupervisionTypeIndicator = 0x15,
|
|
RangeAndStatus = 0x16,
|
|
CallModificationIndicators = 0x17, // ANSI only
|
|
FacilityIndicator = 0x18,
|
|
FacilityInformationIndicators = 0x19, // ANSI only
|
|
CUG_InterlockCode = 0x1a,
|
|
Index = 0x1b, // ANSI only
|
|
CUG_CheckResponseIndicators = 0x1c, // ANSI only
|
|
UserServiceInformation = 0x1d,
|
|
SignallingPointCode = 0x1e,
|
|
UserToUserInformation = 0x20,
|
|
ConnectedNumber = 0x21,
|
|
SuspendResumeIndicators = 0x22,
|
|
TransitNetworkSelection = 0x23,
|
|
EventInformation = 0x24,
|
|
CircuitAssignmentMap = 0x25, // ANSI only
|
|
CircuitStateIndicator = 0x26,
|
|
AutomaticCongestionLevel = 0x27,
|
|
OriginalCalledNumber = 0x28,
|
|
OptionalBackwardCallIndicators = 0x29,
|
|
UserToUserIndicators = 0x2a,
|
|
OriginationISCPointCode = 0x2b, // ITU only
|
|
GenericNotification = 0x2c, // ITU only
|
|
CallHistoryInformation = 0x2d, // ITU only
|
|
AccessDeliveryInformation = 0x2e, // ITU only
|
|
NetworkSpecificFacilities = 0x2f, // ITU only
|
|
UserServiceInformationPrime = 0x30,
|
|
PropagationDelayCounter = 0x31, // ITU only
|
|
RemoteOperations = 0x32,
|
|
ServiceActivation = 0x33,
|
|
UserTeleserviceInformation = 0x34, // ITU only
|
|
TransmissionMediumUsed = 0x35,
|
|
CallDiversionInformation = 0x36, // ITU only
|
|
EchoControlInformation = 0x37, // ITU only
|
|
MessageCompatInformation = 0x38, // ITU only
|
|
ParameterCompatInformation = 0x39, // ITU only
|
|
MLPP_Precedence = 0x3a, // ITU name
|
|
Precedence = MLPP_Precedence, // ANSI name
|
|
MCID_RequestIndicator = 0x3b, // ITU only
|
|
MCID_ResponseIndicator = 0x3c, // ITU only
|
|
HopCounter = 0x3d,
|
|
TransMediumRequirementPrime = 0x3e, // ITU only
|
|
LocationNumber = 0x3f, // ITU only
|
|
RedirectionNumberRestriction = 0x40, // ITU only
|
|
FreephoneIndicators = 0x41, // ITU only
|
|
GenericReference = 0x42, // ITU only
|
|
ApplicationTransport = 0x78,
|
|
GenericNumber = 0xc0, // ITU name
|
|
GenericAddress = GenericNumber, // ANSI name
|
|
GenericDigits = 0xc1,
|
|
OperatorServicesInformation = 0xc2, // ANSI only
|
|
Egress = 0xc3, // ANSI only
|
|
Jurisdiction = 0xc4, // ANSI only
|
|
CarrierIdentification = 0xc5, // ANSI only
|
|
BusinessGroup = 0xc6, // ANSI only
|
|
GenericName = 0xc7, // ANSI only
|
|
NotificationIndicator = 0xe1, // ANSI only
|
|
TransactionRequest = 0xe3, // ANSI only
|
|
CircuitGroupCharactIndicator = 0xe5, // ANSI only
|
|
CircuitValidationRespIndicator = 0xe6, // ANSI only
|
|
OutgoingTrunkGroupNumber = 0xe7, // ANSI only
|
|
CircuitIdentificationName = 0xe8, // ANSI only
|
|
CommonLanguage = 0xe9, // ANSI only
|
|
OriginatingLineInformation = 0xea, // ANSI only
|
|
ChargeNumber = 0xeb, // ANSI only
|
|
ServiceCodeIndicator = 0xec, // ANSI only
|
|
SpecialProcessingRequest = 0xed, // ANSI only
|
|
CarrierSelectionInformation = 0xee, // ANSI only
|
|
NetworkTransport = 0xef, // ANSI only
|
|
};
|
|
|
|
/**
|
|
* Constructor
|
|
* @param type Type of ISUP message as enumeration
|
|
* @param cic Source/destination Circuit Identification Code
|
|
*/
|
|
inline SS7MsgISUP(Type type, unsigned int cic)
|
|
: SignallingMessage(lookup(type,"Unknown")), m_type(type), m_cic(cic)
|
|
{ }
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~SS7MsgISUP()
|
|
{ }
|
|
|
|
/**
|
|
* Get the type of this message
|
|
* @return The type of this message as enumeration
|
|
*/
|
|
inline Type type() const
|
|
{ return m_type; }
|
|
|
|
/**
|
|
* Get the source/destination Circuit Identification Code of this message
|
|
* @return The source/destination Circuit Identification Code of this message
|
|
*/
|
|
inline unsigned int cic() const
|
|
{ return m_cic; }
|
|
|
|
/**
|
|
* Fill a string with this message's parameters for debug purposes
|
|
* @param dest The destination string
|
|
* @param label The routing label
|
|
* @param params True to add parameters
|
|
* @param raw Optional raw message data to be added to destination
|
|
* @param rawLen Raw data length
|
|
*/
|
|
void toString(String& dest, const SS7Label& label, bool params,
|
|
const void* raw = 0, unsigned int rawLen = 0) const;
|
|
|
|
/**
|
|
* Get the dictionary with the message names
|
|
* @return Pointer to the dictionary with the message names
|
|
*/
|
|
static const TokenDict* names();
|
|
|
|
/**
|
|
* Convert an ISUP message type to a C string
|
|
* @param type Type of ISUP message to look up
|
|
* @param defvalue Default string to return
|
|
* @return Name of the ISUP message type
|
|
*/
|
|
static inline const char* lookup(Type type, const char* defvalue = 0)
|
|
{ return TelEngine::lookup(type,names(),defvalue); }
|
|
|
|
/**
|
|
* Look up an ISUP message name
|
|
* @param name String name of the ISUP message
|
|
* @param defvalue Default type to return
|
|
* @return Encoded type of the ISUP message
|
|
*/
|
|
static inline Type lookup(const char* name, Type defvalue = Unknown)
|
|
{ return static_cast<Type>(TelEngine::lookup(name,names(),defvalue)); }
|
|
|
|
private:
|
|
Type m_type; // Message type
|
|
unsigned int m_cic; // Source/destination Circuit Identification Code
|
|
};
|
|
|
|
/**
|
|
* Implementation of SS7 SNM User Part (Management) - Q.704
|
|
* @short SS7 SNM implementation
|
|
*/
|
|
class YSIG_API SS7Management : public SS7Layer4
|
|
{
|
|
YCLASS(SS7Management,SS7Layer4)
|
|
public:
|
|
/**
|
|
* Constructor
|
|
*/
|
|
inline SS7Management(const NamedList& params)
|
|
: SignallingComponent(params.safe("SS7Management"),¶ms)
|
|
{ }
|
|
|
|
protected:
|
|
/**
|
|
* Process a MSU received from a Layer 3 component
|
|
* @param msu Message data, starting with Service Indicator Octet
|
|
* @param label Routing label of the received MSU
|
|
* @param network Network layer that delivered the MSU
|
|
* @param sls Signalling Link the MSU was received from
|
|
* @return True if the MSU was processed
|
|
*/
|
|
virtual bool receivedMSU(const SS7MSU& msu, const SS7Label& label, SS7Layer3* network, int sls);
|
|
|
|
/**
|
|
* Process a notification generated by the attached network layer
|
|
* @param link Network or linkset that generated the notification
|
|
* @param sls Signallink Link that generated the notification, negative if none
|
|
* @return True if notification was processed
|
|
*/
|
|
virtual void notify(SS7Layer3* link, int sls);
|
|
};
|
|
|
|
/**
|
|
* Implementation of SS7 MTN User Part (Maintenance) - Q.707
|
|
* @short SS7 MTN implementation
|
|
*/
|
|
class YSIG_API SS7Maintenance : public SS7Layer4
|
|
{
|
|
YCLASS(SS7Maintenance,SS7Layer4)
|
|
public:
|
|
/**
|
|
* Constructor
|
|
*/
|
|
inline SS7Maintenance(const NamedList& params)
|
|
: SignallingComponent(params.safe("SS7Maintenance"),¶ms)
|
|
{ }
|
|
|
|
protected:
|
|
/**
|
|
* Process a MSU received from a Layer 3 component
|
|
* @param msu Message data, starting with Service Indicator Octet
|
|
* @param label Routing label of the received MSU
|
|
* @param network Network layer that delivered the MSU
|
|
* @param sls Signalling Link the MSU was received from
|
|
* @return True if the MSU was processed
|
|
*/
|
|
virtual bool receivedMSU(const SS7MSU& msu, const SS7Label& label, SS7Layer3* network, int sls);
|
|
|
|
/**
|
|
* Process a notification generated by the attached network layer
|
|
* @param link Network or linkset that generated the notification
|
|
* @param sls Signallink Link that generated the notification, negative if none
|
|
* @return True if notification was processed
|
|
*/
|
|
virtual void notify(SS7Layer3* link, int sls);
|
|
};
|
|
|
|
/**
|
|
* A signalling call using SS7 ISUP protocol
|
|
* @short An SS7 ISUP call
|
|
*/
|
|
class YSIG_API SS7ISUPCall : public SignallingCall
|
|
{
|
|
friend class SS7ISUP;
|
|
public:
|
|
/**
|
|
* Call state enumerators
|
|
*/
|
|
enum State {
|
|
// NOTE: Keep the order of state values: the code relies on it
|
|
Null = 0, // No message exchanged
|
|
Setup = 1, // IAM (initial address)
|
|
Accepted = 2, // ACM (address complete)
|
|
Ringing = 3, // CPM (call progress)
|
|
Answered = 4, // ANM (answer)
|
|
Releasing = 5, // REL (release)
|
|
Released = 6 // Call released, no message or events allowed
|
|
};
|
|
|
|
/**
|
|
* Destructor.
|
|
* Complete call release. Releas circuit. Remove itself from controller's list
|
|
*/
|
|
virtual ~SS7ISUPCall();
|
|
|
|
/**
|
|
* Get the call state
|
|
* @return The call state as enumeration
|
|
*/
|
|
inline State state() const
|
|
{ return m_state; }
|
|
|
|
/**
|
|
* Get the call's circuit range
|
|
* @return The call's circuit range
|
|
*/
|
|
inline const String& cicRange() const
|
|
{ return m_cicRange; }
|
|
|
|
/**
|
|
* Get the call id (the code of the circuit reserved for this call)
|
|
* @return The call id
|
|
*/
|
|
inline unsigned int id() const
|
|
{ return m_circuit ? m_circuit->code() : 0; }
|
|
|
|
/**
|
|
* Get an event from this call
|
|
* This method is thread safe
|
|
* @param when The current time
|
|
* @return SignallingEvent pointer or 0 if no events
|
|
*/
|
|
virtual SignallingEvent* getEvent(const Time& when);
|
|
|
|
/**
|
|
* Send an event to this call
|
|
* @param event The event to send
|
|
* @return True if the operation succedded
|
|
*/
|
|
virtual bool sendEvent(SignallingEvent* event);
|
|
|
|
/**
|
|
* Set termination flag. Set termination reason if not already set
|
|
* @param gracefully True to send RLC on termination, false to destroy the call without notification
|
|
* @param reason Termination reason
|
|
*/
|
|
inline void setTerminate(bool gracefully, const char* reason = 0)
|
|
{
|
|
Lock lock(this);
|
|
m_terminate = true;
|
|
m_gracefully = gracefully;
|
|
setReason(reason,0);
|
|
}
|
|
|
|
/**
|
|
* Get a pointer to this object or other data
|
|
* @param name Object name
|
|
* @return The requested pointer or 0 if not exists
|
|
*/
|
|
virtual void* getObject(const String& name) const;
|
|
|
|
protected:
|
|
/**
|
|
* Constructor
|
|
* @param controller The call controller
|
|
* @param cic The reserved circuit
|
|
* @param local The local point code used to create the routing label for sent messages
|
|
* @param remote The remote point code used to create the routing label for sent messages
|
|
* @param outgoing Call direction
|
|
* @param sls Optional link for the routing label
|
|
* @param range Optional range used to re-allocate a circuit for this call if necessary
|
|
*/
|
|
SS7ISUPCall(SS7ISUP* controller, SignallingCircuit* cic,
|
|
const SS7PointCode& local, const SS7PointCode& remote, bool outgoing,
|
|
int sls = -1, const char* range = 0);
|
|
|
|
/**
|
|
* Release call. Stop timers. Send a RLC (Release Complete) message if it should terminate gracefully
|
|
* Decrease the object's refence count and generate a Release event if not final
|
|
* This method is thread safe
|
|
* @param final True if called from destructor
|
|
* @param msg Received message with parameters if any
|
|
* @param reason Optional release reason
|
|
* @return SignallingEvent pointer or 0
|
|
*/
|
|
SignallingEvent* releaseComplete(bool final, SS7MsgISUP* msg = 0, const char* reason = 0);
|
|
|
|
/**
|
|
* Replace the circuit reserved for this call. Release the already reserved circuit.
|
|
* Retransmit the initial IAM request on success.
|
|
* On failure set the termination flag and release the new circuit if valid.
|
|
* If false is returned, the call is prepared to return a Release event.
|
|
* This method is thread safe
|
|
* @param circuit The new circuit reserved for this call
|
|
* @return False if the state is greater then Setup, the call is not outgoing or the new circuit is 0
|
|
*/
|
|
bool replaceCircuit(SignallingCircuit* circuit);
|
|
|
|
/**
|
|
* Stop waiting for a SGM (Segmentation) message when another message is received by the controller.
|
|
* This method is thread safe
|
|
* @param discard True to discard (destruct) the segment waiting message if any
|
|
*/
|
|
void stopWaitSegment(bool discard);
|
|
|
|
private:
|
|
// Initialize/set IAM message parameters
|
|
// @param msg Valid ISUP message
|
|
// @param outgoing Message direction: true for outgoing
|
|
// @param sigMsg Valid signalling message with parameters if outgoing
|
|
bool copyParamIAM(SS7MsgISUP* msg, bool outgoing = false, SignallingMessage* sigMsg = 0);
|
|
// If already releasing, set termination flag. Otherwise, send REL (Release) message
|
|
// @param event Event with the parameters. 0 if release is started on some timeout
|
|
// @return True if the message was pushed down the protocol stack
|
|
bool release(SignallingEvent* event = 0);
|
|
// Set termination reason from message or parameter
|
|
void setReason(const char* reason, SignallingMessage* msg);
|
|
// Accept send/receive messages in current state based on call direction
|
|
bool validMsgState(bool send, SS7MsgISUP::Type type);
|
|
// Connect the reserved circuit. Return false if it fails. Return true if this call is a signalling only one
|
|
bool connectCircuit();
|
|
// Transmit the IAM message. Start IAM timer if not started
|
|
bool transmitIAM();
|
|
// Stop waiting for a SGM (Segmentation) message. Copy parameters to the pending segmented message if sgm is valid.
|
|
// Change call state and set m_lastEvent
|
|
// @param sgm Optional received SGM message with parameters to be added to the pending segmented message
|
|
// @param timeout True if waiting timer timed out. Ignored if sgm is non null
|
|
// @return m_lastEvent
|
|
SignallingEvent* processSegmented(SS7MsgISUP* sgm = 0, bool timeout = false);
|
|
// Transmit message. Set routing label's link if not already set
|
|
inline bool transmitMessage(SS7MsgISUP* msg);
|
|
// Get the ISUP call controller
|
|
inline SS7ISUP* isup();
|
|
|
|
State m_state; // Call state
|
|
SignallingCircuit* m_circuit; // Circuit reserved for this call
|
|
String m_cicRange; // The range used to re(alloc) a circuit
|
|
SS7Label m_label; // The routing label for this call
|
|
bool m_terminate; // Termination flag
|
|
bool m_gracefully; // Terminate gracefully: send RLC
|
|
bool m_circuitChanged; // circuit change flag
|
|
String m_format; // Data format used by the circuit
|
|
String m_reason; // Termination reason
|
|
SS7MsgISUP* m_iamMsg; // Message with the call parameters for outgoing calls
|
|
SS7MsgISUP* m_sgmMsg; // Pending received message with segmentation flag set
|
|
// Timers
|
|
SignallingTimer m_relTimer; // Send release
|
|
SignallingTimer m_iamTimer; // Send initial address
|
|
SignallingTimer m_sgmRecvTimer; // Receive segmented message
|
|
};
|
|
|
|
/**
|
|
* Implementation of SS7 ISDN User Part
|
|
* @short SS7 ISUP implementation
|
|
*/
|
|
class YSIG_API SS7ISUP : public SignallingCallControl, public SS7Layer4
|
|
{
|
|
YCLASS(SS7ISUP,SS7Layer4)
|
|
friend class SS7ISUPCall;
|
|
public:
|
|
/**
|
|
* Constructor
|
|
* @param params Call controller's parameters
|
|
*/
|
|
SS7ISUP(const NamedList& params);
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~SS7ISUP();
|
|
|
|
/**
|
|
* Configure and initialize the call controller and user part
|
|
* @param config Optional configuration parameters override
|
|
* @return True if ISUP was initialized properly
|
|
*/
|
|
virtual bool initialize(const NamedList* config);
|
|
|
|
/**
|
|
* Get the length of the Circuit Identification Code for this user part
|
|
* @return Length of the CIC field in octets
|
|
*/
|
|
unsigned int cicLen() const
|
|
{ return m_cicLen; }
|
|
|
|
/**
|
|
* Get the default data format
|
|
* @return The default data format
|
|
*/
|
|
const String& format() const
|
|
{ return m_format; }
|
|
|
|
/**
|
|
* Append a point code to the list of point codes serviced by this controller
|
|
* if not already there. Set default point code if requested.
|
|
* If the list is empty, the default point code is set to the first point code added
|
|
* @param pc The point code to append
|
|
* @param def True if this point code is the default for outgoing calls
|
|
* @return False if the point code is invalid for this call controller type. If true is returned, don't reuse the pointer
|
|
*/
|
|
bool setPointCode(SS7PointCode* pc, bool def);
|
|
|
|
/**
|
|
* Append all point codes from a parameter list, use "pointcode" and
|
|
* "defaultpointcode" parameters
|
|
* @param params List of parameters to take point codes from
|
|
* @return Count of point codes added
|
|
*/
|
|
unsigned int setPointCode(const NamedList& params);
|
|
|
|
/**
|
|
* Check if the given point code is serviced by this controller
|
|
* @param pc The point code to check
|
|
* @return SS7PointCode pointer or 0 if not found
|
|
*/
|
|
SS7PointCode* hasPointCode(const SS7PointCode& pc);
|
|
|
|
/**
|
|
* Set a routing label to be used for outgoing messages
|
|
* @param label Routing label to set
|
|
* @param opc Originating point code
|
|
* @param dpc Destination point code
|
|
* @param sls Signalling Link Selection
|
|
*/
|
|
inline void setLabel(SS7Label& label, const SS7PointCode& opc, const SS7PointCode& dpc,
|
|
unsigned char sls = 255)
|
|
{ label.assign(m_type,dpc,opc,sls); }
|
|
|
|
/**
|
|
* Set debug data of this call controller
|
|
* @param printMsg Enable/disable message printing on output
|
|
* @param extendedDebug Enable/disable hex data dump if print messages is enabled
|
|
*/
|
|
inline void setDebug(bool printMsg, bool extendedDebug)
|
|
{ m_extendedDebug = ((m_printMsg = printMsg) && extendedDebug); }
|
|
|
|
/**
|
|
* Create a new MSU populated with type, routing label and space for fixed part
|
|
* @param type Type of ISUP message
|
|
* @param ssf Subservice Field
|
|
* @param label Routing label for the new MSU
|
|
* @param cic Circuit Identification Code
|
|
* @param params Optional parameter list
|
|
* @return Pointer to the new MSU or NULL if an error occured
|
|
*/
|
|
virtual SS7MSU* createMSU(SS7MsgISUP::Type type, unsigned char ssf,
|
|
const SS7Label& label, unsigned int cic, const NamedList* params = 0) const;
|
|
|
|
/**
|
|
* Create an outgoing call. Send a NewCall event with the given msg parameter
|
|
* This method is thread safe
|
|
* @param msg Call parameters
|
|
* @param reason Failure reason if any
|
|
* @return Referenced SignallingCall pointer on success or 0 on failure
|
|
*/
|
|
virtual SignallingCall* call(SignallingMessage* msg, String& reason);
|
|
|
|
/**
|
|
* Converts an ISUP message to a Message Signal Unit and push it down the protocol stack.
|
|
* The given message is consumed
|
|
* @param msg The message to send
|
|
* @param label The routing label for the message
|
|
* @param recvLbl True if the given label is from a received message. If true, a new routing
|
|
* label will be created from the received one
|
|
* @param sls Signalling Link to use for the new routing label. Ignored if recvLbl is false
|
|
* @return Link the message was successfully queued to, negative for error
|
|
*/
|
|
int transmitMessage(SS7MsgISUP* msg, const SS7Label& label, bool recvLbl, int sls = -1);
|
|
|
|
/**
|
|
* Cleanup calls
|
|
* This method is thread safe
|
|
* @param reason Cleanup reason
|
|
*/
|
|
virtual void cleanup(const char* reason = "offline");
|
|
|
|
/**
|
|
* Decode an ISUP message buffer to a list of parameters
|
|
* @param msg Destination list of parameters
|
|
* @param msgType The message type
|
|
* @param pcType The point code type (message version)
|
|
* @param paramPtr Pointer to the Parameter area (just after the message type)
|
|
* @param paramLen Length of the Parameter area
|
|
* @return True if the mesage was succesfully parsed
|
|
*/
|
|
bool decodeMessage(NamedList& msg, SS7MsgISUP::Type msgType, SS7PointCode::Type pcType,
|
|
const unsigned char* paramPtr, unsigned int paramLen);
|
|
|
|
/**
|
|
* Encode an ISUP list of parameters to a buffer.
|
|
* The input list may contain a 'message-prefix' parameter to override this controller's prefix
|
|
* @param buf Destination buffer
|
|
* @param msgType The message type
|
|
* @param pcType The point code type (message version)
|
|
* @param params Message list of parameters
|
|
* @param cic Optional cic to be added before mesage
|
|
* @return True if the mesage was succesfully encoded
|
|
*/
|
|
bool encodeMessage(DataBlock& buf, SS7MsgISUP::Type msgType, SS7PointCode::Type pcType,
|
|
const NamedList& params, unsigned int* cic = 0);
|
|
|
|
protected:
|
|
/**
|
|
* Remove all links with other layers. Disposes the memory
|
|
*/
|
|
virtual void destroyed();
|
|
|
|
/**
|
|
* Send CGU if not already done. Check timeouts
|
|
* @param when Time to use as computing base for timeouts
|
|
*/
|
|
virtual void timerTick(const Time& when);
|
|
|
|
/**
|
|
* Process a notification generated by the attached network layer
|
|
* @param link Network or linkset that generated the notification
|
|
* @param sls Signalling Link that generated the notification, negative if none
|
|
*/
|
|
virtual void notify(SS7Layer3* link, int sls);
|
|
|
|
/**
|
|
* Create a new MSU populated with type, routing label and space for fixed part
|
|
* @param type Type of ISUP message
|
|
* @param sio Service Information Octet
|
|
* @param label Routing label for the new MSU
|
|
* @param cic Circuit Identification Code
|
|
* @param params Parameter list
|
|
* @return Pointer to the new MSU or NULL if an error occured
|
|
*/
|
|
SS7MSU* buildMSU(SS7MsgISUP::Type type, unsigned char sio,
|
|
const SS7Label& label, unsigned int cic, const NamedList* params) const;
|
|
|
|
/**
|
|
* Process a MSU received from a Layer 3 component
|
|
* @param msu Message data, starting with Service Indicator Octet
|
|
* @param label Routing label of the received MSU
|
|
* @param network Network layer that delivered the MSU
|
|
* @param sls Signalling Link the MSU was received from
|
|
* @return True if the MSU was processed
|
|
*/
|
|
virtual bool receivedMSU(const SS7MSU& msu, const SS7Label& label, SS7Layer3* network, int sls);
|
|
|
|
/**
|
|
* Process a MSU received from a Layer 3 component
|
|
* @param type Type of ISUP message
|
|
* @param cic Circuit Identification Code
|
|
* @param paramPtr Pointer to the Parameter area
|
|
* @param paramLen Length of the Parameter area
|
|
* @param label Routing label of the received MSU
|
|
* @param network Network layer that delivered the MSU
|
|
* @param sls Signalling Link the MSU was received from
|
|
* @return True if the MSU was processed
|
|
*/
|
|
virtual bool processMSU(SS7MsgISUP::Type type, unsigned int cic,
|
|
const unsigned char* paramPtr, unsigned int paramLen,
|
|
const SS7Label& label, SS7Layer3* network, int sls);
|
|
|
|
/**
|
|
* Process an event received from a non-reserved circuit
|
|
* @param event The event, will be consumed and zeroed
|
|
* @param call Optional signalling call whose circuit generated the event
|
|
* @return Signalling event pointer or 0
|
|
*/
|
|
virtual SignallingEvent* processCircuitEvent(SignallingCircuitEvent*& event,
|
|
SignallingCall* call = 0);
|
|
|
|
/**
|
|
* Length of the Circuit Identification Code in octets
|
|
*/
|
|
unsigned int m_cicLen;
|
|
|
|
private:
|
|
// Process a received message that should be processed by a call
|
|
// @param msg The received message
|
|
// @param label The routing label of the received message
|
|
// @param sls Signalling Link the message was received from
|
|
void processCallMsg(SS7MsgISUP* msg, const SS7Label& label, int sls);
|
|
// Process a received message that should be processed by this call controller
|
|
// @param msg The received message
|
|
// @param label The routing label of the received message
|
|
// @param sls Signalling Link the message was received from
|
|
void processControllerMsg(SS7MsgISUP* msg, const SS7Label& label, int sls);
|
|
// Replace a call's circuit if checkCall is true
|
|
// Clear lock flags of the circuit. Release currently reseting circuit if the code match
|
|
// Return false if the given circuit doesn't exist
|
|
bool resetCircuit(unsigned int cic, bool remote, bool checkCall);
|
|
// Block/unblock a circuit side (local or remote)
|
|
// Return false if the given circuit doesn't exist
|
|
bool blockCircuit(unsigned int cic, bool block, bool remote, bool hwFail,
|
|
bool changed, bool changedState);
|
|
// Find a call by its circuit identification code
|
|
SS7ISUPCall* findCall(unsigned int cic);
|
|
// Send blocking/unblocking messages
|
|
// Return false if no request was sent
|
|
bool sendLocalLock(u_int64_t when = Time::msecNow());
|
|
|
|
SS7PointCode::Type m_type; // Point code type of this call controller
|
|
ObjList m_pointCodes; // Point codes serviced by this call controller
|
|
SS7PointCode* m_defPoint; // Default point code for outgoing calls
|
|
SS7PointCode* m_remotePoint; // Default remote point code for outgoing calls and maintenance
|
|
unsigned char m_priossf; // MSU priority + Subservice field
|
|
unsigned char m_sls; // Last known valid SLS
|
|
bool m_earlyAcm; // Accept progress/ringing in early ACM
|
|
bool m_inn; // Routing to internal network number flag
|
|
String m_numPlan; // Numbering plan
|
|
String m_numType; // Number type
|
|
String m_numPresentation; // Number presentation
|
|
String m_numScreening; // Number screening
|
|
String m_callerCat; // Caller party category
|
|
String m_format; // Default format
|
|
bool m_l3LinkUp; // Flag indicating the availability of a Layer3 data link
|
|
// Remote User Part test
|
|
SignallingTimer m_uptTimer; // Timer for UPT
|
|
bool m_userPartAvail; // Flag indicating the remote User Part availability
|
|
unsigned int m_uptCicCode; // The circuit code sent with UPT
|
|
// Circuit reset
|
|
SignallingTimer m_rscTimer; // RSC message or idle timeout
|
|
SignallingCircuit* m_rscCic; // Circuit currently beeing reset
|
|
// Blocking/unblocking circuits
|
|
SignallingTimer m_lockTimer; // Request timeout
|
|
bool m_lockGroup; // Allow sending requests for a group
|
|
bool m_lockNeed; // Flag used to signal that there are circuits whose lock state changed
|
|
bool m_hwFailReq; // HW failure/maintenance block/unblock sent
|
|
bool m_blockReq; // Block/unblock req. sent
|
|
unsigned int m_lockCicCode; // Current (un)blocking cic code
|
|
String m_lockMap; // The sent circuit map (contains 1 element for single circuit request)
|
|
// Debug flags
|
|
bool m_printMsg; // Print messages to output
|
|
bool m_extendedDebug; // Extended debug flag
|
|
};
|
|
|
|
/**
|
|
* Implementation of SS7 Bearer Independent Call Control User Part
|
|
* @short SS7 BICC implementation
|
|
*/
|
|
class YSIG_API SS7BICC : public SS7ISUP
|
|
{
|
|
YCLASS(SS7BICC,SS7ISUP)
|
|
public:
|
|
/**
|
|
* Constructor
|
|
* @param params Call controller's parameters
|
|
*/
|
|
SS7BICC(const NamedList& params);
|
|
|
|
/**
|
|
* Destructor
|
|
* Terminate all calls
|
|
*/
|
|
virtual ~SS7BICC();
|
|
|
|
/**
|
|
* Create a new MSU populated with type, routing label and space for fixed part
|
|
* @param type Type of ISUP message
|
|
* @param ssf Subservice Field
|
|
* @param label Routing label for the new MSU
|
|
* @param cic Circuit Identification Code
|
|
* @param params Optional parameter list
|
|
* @return Pointer to the new MSU or NULL if an error occured
|
|
*/
|
|
virtual SS7MSU* createMSU(SS7MsgISUP::Type type, unsigned char ssf,
|
|
const SS7Label& label, unsigned int cic, const NamedList* params = 0) const;
|
|
|
|
protected:
|
|
/**
|
|
* Process a MSU received from a Layer 3 component
|
|
* @param msu Message data, starting with Service Indicator Octet
|
|
* @param label Routing label of the received MSU
|
|
* @param network Network layer that delivered the MSU
|
|
* @param sls Signalling Link the MSU was received from
|
|
* @return True if the MSU was processed
|
|
*/
|
|
virtual bool receivedMSU(const SS7MSU& msu, const SS7Label& label, SS7Layer3* network, int sls);
|
|
};
|
|
|
|
/**
|
|
* Implementation of SS7 Telephone User Part
|
|
* @short SS7 TUP implementation
|
|
*/
|
|
class YSIG_API SS7TUP : public SignallingCallControl, public SS7Layer4
|
|
{
|
|
public:
|
|
SS7TUP(const NamedList& params);
|
|
virtual ~SS7TUP();
|
|
};
|
|
|
|
/**
|
|
* Implementation of SS7 Signalling Connection Control Part
|
|
* @short SS7 SCCP implementation
|
|
*/
|
|
class YSIG_API SS7SCCP : public SS7Layer4, public SCCP
|
|
{
|
|
};
|
|
|
|
/**
|
|
* RFC3868 SS7 SCCP implementation over SCTP/IP
|
|
* SUA is intended to be used as a Provider-User where real SCCP runs on a
|
|
* Signalling Gateway and SCCP users are located on an Application Server.
|
|
* @short SIGTRAN SCCP User Adaptation Layer
|
|
*/
|
|
class YSIG_API SS7SUA : public SIGTRAN, public SCCP
|
|
{
|
|
};
|
|
|
|
/**
|
|
* Implementation of SS7 Application Service Part
|
|
* @short SS7 ASP implementation
|
|
*/
|
|
class YSIG_API SS7ASP : public SCCPUser, virtual public SignallingComponent
|
|
{
|
|
protected:
|
|
ObjList m_sccps;
|
|
};
|
|
|
|
/**
|
|
* Implementation of SS7 Transactional Capabilities Application Part
|
|
* @short SS7 TCAP implementation
|
|
*/
|
|
class YSIG_API SS7TCAP : public ASPUser, virtual public SignallingComponent
|
|
{
|
|
/**
|
|
* Attach a SS7 TCAP user
|
|
* @param user Pointer to the TCAP user to attach
|
|
*/
|
|
void attach(TCAPUser* user);
|
|
|
|
protected:
|
|
ObjList m_users;
|
|
};
|
|
|
|
// The following classes are ISDN, not SS7, but they use the same signalling
|
|
// interfaces so they will remain here
|
|
|
|
/**
|
|
* An interface to a Layer 2 (Q.921) ISDN message transport
|
|
* @short Abstract ISDN layer 2 (Q.921) message transport
|
|
*/
|
|
class YSIG_API ISDNLayer2 : virtual public SignallingComponent
|
|
{
|
|
YCLASS(ISDNLayer2,SignallingComponent)
|
|
friend class ISDNQ921Management;
|
|
public:
|
|
/**
|
|
* Layer states if it has a TEI assigned
|
|
*/
|
|
enum State {
|
|
Released, // Multiple frame acknowledged not allowed
|
|
WaitEstablish, // Wating to establish 'multiple frame acknowledged' mode
|
|
Established, // Multiple frame acknowledged allowed
|
|
WaitRelease, // Wating to release 'multiple frame acknowledged' mode
|
|
};
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~ISDNLayer2();
|
|
|
|
/**
|
|
* Get the ISDN Layer 3 attached to this layer
|
|
*/
|
|
inline ISDNLayer3* layer3() const
|
|
{ return m_layer3; }
|
|
|
|
/**
|
|
* Get the layer's state
|
|
* @return The layer's state as enumeration
|
|
*/
|
|
inline State state() const
|
|
{ return m_state; }
|
|
|
|
/**
|
|
* Check if this interface is the network or CPE (user) side of the link
|
|
* @return True if this interface is the network side of the link
|
|
*/
|
|
inline bool network() const
|
|
{ return m_network; }
|
|
|
|
/**
|
|
* Check if this interface should change its type
|
|
* @return True if type change is allowed
|
|
*/
|
|
inline bool detectType() const
|
|
{ return m_detectType; }
|
|
|
|
/**
|
|
* Get the SAPI (Service Access Point Identifier) of this interface
|
|
* @return The SAPI (Service Access Point Identifier) of this interface
|
|
*/
|
|
inline u_int8_t localSapi() const
|
|
{ return m_sapi; }
|
|
|
|
/**
|
|
* Get the TEI (Terminal Endpoint Identifier) of this interface
|
|
* @return The TEI (Terminal Endpoint Identifier) of this interface
|
|
*/
|
|
inline u_int8_t localTei() const
|
|
{ return m_tei; }
|
|
|
|
/**
|
|
* Get the maximum length of user data transported through this layer
|
|
* @return The maximum length of user data transported through this layer
|
|
*/
|
|
inline u_int32_t maxUserData() const
|
|
{ return m_maxUserData; }
|
|
|
|
/**
|
|
* Check if this interface has a TEI assigned
|
|
* @return True if this interface has a TEI assigned
|
|
*/
|
|
inline bool teiAssigned() const
|
|
{ return m_teiAssigned; }
|
|
|
|
/**
|
|
* Check if this interface will automatically re-establish when released
|
|
* @return The auto restart flag
|
|
*/
|
|
inline bool autoRestart() const
|
|
{ return m_autoRestart; }
|
|
|
|
/**
|
|
* Implements Q.921 DL-ESTABLISH and DL-RELEASE request primitives
|
|
* Descendants must implement this method to fullfill the request
|
|
* @param tei This layer TEI (Terminal Endpoint Identifier)
|
|
* @param establish True to establish. False to release
|
|
* @param force True to establish even if we already are in this mode. This
|
|
* parameter is ignored if establish is false
|
|
* @return True if the request was accepted
|
|
*/
|
|
virtual bool multipleFrame(u_int8_t tei, bool establish, bool force)
|
|
{ return false; }
|
|
|
|
/**
|
|
* Implements Q.921 DL-DATA and DL-UNIT DATA request primitives
|
|
* Descendants must implement this method to fullfill the request
|
|
* @param data Data to send
|
|
* @param tei This layer TEI
|
|
* @param ack True to send an acknowledged frame, false to send an unacknowledged one
|
|
* @return True if the request was accepted
|
|
*/
|
|
virtual bool sendData(const DataBlock& data, u_int8_t tei, bool ack)
|
|
{ return false; }
|
|
|
|
/**
|
|
* Emergency release.
|
|
* Descendants must implement this method to cleanup/reset data
|
|
*/
|
|
virtual void cleanup() = 0;
|
|
|
|
/**
|
|
* Attach an ISDN Q.931 Layer 3 if the given parameter is different from the one we have
|
|
* Cleanup the object before ataching the new Layer 3
|
|
* This method is thread safe
|
|
* @param layer3 Pointer to the Q.931 Layer 3 to attach
|
|
*/
|
|
virtual void attach(ISDNLayer3* layer3);
|
|
|
|
/**
|
|
* Get the text associated with a given state
|
|
* @param s The state to get the text for
|
|
* @return The text associated with the given state
|
|
*/
|
|
static inline const char* stateName(State s)
|
|
{ return lookup((int)s,m_states); }
|
|
|
|
protected:
|
|
/**
|
|
* Constructor
|
|
* Initialize this interface and the component
|
|
* @param params Layer's parameters
|
|
* @param name Optional name of the component
|
|
* @param tei Value of TEI for this layer
|
|
*/
|
|
ISDNLayer2(const NamedList& params, const char* name = 0, u_int8_t tei = 0);
|
|
|
|
/**
|
|
* Retrieve the layer's mutex
|
|
* @return Reference to the Layer 2 mutex
|
|
*/
|
|
inline Mutex& l2Mutex()
|
|
{ return m_layerMutex; }
|
|
|
|
/**
|
|
* Implements Q.921 DL-ESTABLISH indication/confirmation primitive
|
|
* of 'multiple frame acknowledged' mode established
|
|
* @param tei The TEI requested
|
|
* @param confirm True if this is a confirmation of a previous request.
|
|
* False if it is an indication of state change on remote request
|
|
* @param timeout True if the reason is a timeout.
|
|
*/
|
|
void multipleFrameEstablished(u_int8_t tei, bool confirm, bool timeout);
|
|
|
|
/**
|
|
* Implements Q.921 DL-RELEASE indication/confirmation primitive
|
|
* of 'multiple frame acknowledged' mode released
|
|
* @param tei The TEI released
|
|
* @param confirm True if this is a confirmation of a previous request.
|
|
* False if it is an indication of state change on remote request
|
|
* @param timeout True if the reason is a timeout.
|
|
*/
|
|
void multipleFrameReleased(u_int8_t tei, bool confirm, bool timeout);
|
|
|
|
/**
|
|
* Notify layer 3 of data link set/release command or response
|
|
* Used for stateless layer 2
|
|
* @param tei The TEI of this layer
|
|
* @param cmd True if received a command, false if received a response
|
|
* @param value The value of the notification
|
|
* If 'cmd' is true (command), the value is true if a request to establish data link was received
|
|
* or false if received a request to release data link
|
|
* If 'cmd' is false (response), the value is the response
|
|
*/
|
|
void dataLinkState(u_int8_t tei, bool cmd, bool value);
|
|
|
|
/**
|
|
* Notify layer 3 of data link idle timeout
|
|
* Used for stateless layer 2
|
|
*/
|
|
void idleTimeout();
|
|
|
|
/**
|
|
* Implements Q.921 DL-DATA and DL-UNIT DATA indication primitives
|
|
* Receive data from remote peer
|
|
* @param data Received data
|
|
* @param tei The TEI for which the data was received
|
|
*/
|
|
void receiveData(const DataBlock& data, u_int8_t tei);
|
|
|
|
/**
|
|
* Set TEI assigned status. Print a debug message. If status is false calls cleanup()
|
|
* Descendants are responsable for TEI assigned status management
|
|
* @param status The new TEI assigned status
|
|
*/
|
|
void teiAssigned(bool status);
|
|
|
|
/**
|
|
* Set the state
|
|
* Descendants are responsable for multiple frame status management
|
|
* @param newState The new state
|
|
* @param reason Reason of state change, NULL if unspecified
|
|
*/
|
|
void changeState(State newState, const char* reason = 0);
|
|
|
|
/**
|
|
* Change the interface type
|
|
* @return True if interface type changed
|
|
*/
|
|
bool changeType();
|
|
|
|
/**
|
|
* Set the automatically re-establish when released flag
|
|
* @param restart The new value of the auto restart flag
|
|
*/
|
|
inline void autoRestart(bool restart)
|
|
{ m_autoRestart = restart; }
|
|
|
|
/**
|
|
* Set the Reference Identifier used in management procedures
|
|
* @param ri The new reference number
|
|
*/
|
|
inline void setRi(u_int16_t ri)
|
|
{ m_ri = ri; }
|
|
|
|
/**
|
|
* Parse a received packet
|
|
* @param packet The packet received
|
|
* @return Pointer to a newly created frame, NULL if an error occured
|
|
*/
|
|
ISDNFrame* parsePacket(const DataBlock& packet);
|
|
|
|
private:
|
|
ISDNLayer3* m_layer3; // The attached Layer 3 interface
|
|
Mutex m_layerMutex; // Layer 2 operations mutex
|
|
Mutex m_layer3Mutex; // Control m_layer3 operations
|
|
State m_state; // Layer's state
|
|
bool m_network; // Network/CPE type of the interface
|
|
bool m_detectType; // Detect interface type
|
|
u_int8_t m_sapi; // SAPI value
|
|
u_int8_t m_tei; // TEI value
|
|
u_int16_t m_ri; // Reference number
|
|
bool m_checked; // Flag to indicate if the layer was checked
|
|
bool m_teiAssigned; // The TEI status
|
|
bool m_autoRestart; // True to restart when released
|
|
u_int32_t m_maxUserData; // Maximum length of user data transported trough this layer
|
|
unsigned int m_teiRefNumber; // The Reference Number (Ri) carried by a TEI management frame
|
|
static TokenDict m_states[]; // Keep the string associated with each state
|
|
};
|
|
|
|
/**
|
|
* An interface to a Layer 3 (Q.931) ISDN message transport
|
|
* @short Abstract ISDN layer 3 (Q.931) message transport
|
|
*/
|
|
class YSIG_API ISDNLayer3 : virtual public SignallingComponent
|
|
{
|
|
YCLASS(ISDNLayer3,SignallingComponent)
|
|
public:
|
|
/**
|
|
* Implements Q.921 DL-ESTABLISH indication/confirmation primitive:
|
|
* 'multiple frame acknowledged' mode established
|
|
* @param tei The TEI of the frame
|
|
* @param confirm True if this is a confirmation of a previous request.
|
|
* False if it is an indication of state change on remote request
|
|
* @param timeout True if the reason is a timeout
|
|
* @param layer2 Pointer to the notifier
|
|
*/
|
|
virtual void multipleFrameEstablished(u_int8_t tei, bool confirm, bool timeout, ISDNLayer2* layer2)
|
|
{ }
|
|
|
|
/**
|
|
* Implements Q.921 DL-RELEASE indication/confirmation primitive:
|
|
* 'multiple frame acknowledged' mode released
|
|
* @param tei The TEI of the frame
|
|
* @param confirm True if this is a confirmation of a previous request.
|
|
* False if it is an indication of state change on remote request
|
|
* @param timeout True if the reason is a timeout.
|
|
* @param layer2 Pointer to the notifier
|
|
*/
|
|
virtual void multipleFrameReleased(u_int8_t tei, bool confirm, bool timeout, ISDNLayer2* layer2)
|
|
{ }
|
|
|
|
/**
|
|
* Notification from layer 2 of data link set/release command or response
|
|
* Used for stateless layer 2
|
|
* @param tei The TEI of the command or response
|
|
* @param cmd True if received a command, false if received a response
|
|
* @param value The value of the notification
|
|
* If 'cmd' is true (command), the value is true if a request to establish data link was received
|
|
* or false if received a request to release data link
|
|
* If 'cmd' is false (response), the value is the response
|
|
* @param layer2 Pointer to the notifier
|
|
*/
|
|
virtual void dataLinkState(u_int8_t tei, bool cmd, bool value, ISDNLayer2* layer2)
|
|
{ }
|
|
|
|
/**
|
|
* Notification from layer 2 of data link idle timeout
|
|
* Used for stateless layer 2
|
|
* @param layer2 Pointer to the notifier
|
|
*/
|
|
virtual void idleTimeout(ISDNLayer2* layer2)
|
|
{ }
|
|
|
|
/**
|
|
* Implements Q.921 DL-DATA and DL-UNIT DATA indication primitives
|
|
* Receive data from remote peer
|
|
* @param data Received data
|
|
* @param tei The TEI of the received frame
|
|
* @param layer2 Pointer to the sender
|
|
*/
|
|
virtual void receiveData(const DataBlock& data, u_int8_t tei, ISDNLayer2* layer2) = 0;
|
|
|
|
/**
|
|
* Attach an ISDN Q.921 Layer 2
|
|
* @param layer2 Pointer to the Q.921 Layer 2 to attach
|
|
* @return Pointer to the detached Layer 2 or NULL
|
|
*/
|
|
virtual ISDNLayer2* attach(ISDNLayer2* layer2)
|
|
{ return 0; }
|
|
|
|
protected:
|
|
/**
|
|
* Constructor
|
|
* Initialize the component
|
|
* @param name Name of this component
|
|
*/
|
|
inline ISDNLayer3(const char* name = 0)
|
|
: SignallingComponent(name),
|
|
m_layerMutex(true,"ISDNLayer3::layer")
|
|
{ }
|
|
|
|
/**
|
|
* Retrieve the layer's mutex
|
|
* @return Reference to the Layer 3 mutex
|
|
*/
|
|
inline Mutex& l3Mutex()
|
|
{ return m_layerMutex; }
|
|
|
|
private:
|
|
Mutex m_layerMutex; // Layer 3 operations mutex
|
|
};
|
|
|
|
/**
|
|
* Encapsulates an ISDN (Q.921) frame exchanged over a hardware HDLC interface
|
|
* @short An ISDN frame
|
|
*/
|
|
class YSIG_API ISDNFrame : public RefObject
|
|
{
|
|
friend class ISDNQ921;
|
|
friend class ISDNQ921Management;
|
|
public:
|
|
/**
|
|
* Frame type according to Q.921 3.6
|
|
*/
|
|
enum Type {
|
|
DISC = 1, // disconnect (command)
|
|
DM = 2, // disconnected (response)
|
|
FRMR = 3, // frame reject (response)
|
|
I = 4, // information transfer (response)
|
|
REJ = 5, // reject (command/response)
|
|
RNR = 6, // receive not ready (command/response)
|
|
RR = 7, // receive ready (command/response)
|
|
SABME = 8, // set asynchronous balanced mode extended (command)
|
|
UA = 9, // unnumbered acknoledgement (response)
|
|
UI = 10, // unnumbered information (command)
|
|
XID = 11, // exchange identification (command/response)
|
|
// Note: Keep all errors greater then Invalid: The code relies on it
|
|
Invalid = 100,
|
|
ErrUnknownCR = 101, // Error: Unknown command/response. Set by parser
|
|
ErrHdrLength = 102, // Error: Invalid header length. Set by parser
|
|
ErrDataLength = 103, // Error: Information field too long
|
|
ErrRxSeqNo = 104, // Error: Invalid receive sequence number
|
|
ErrTxSeqNo = 105, // Error: Invalid send sequence number
|
|
ErrInvalidEA = 106, // Error: Invalid 'extended address' bit(s). Set by parser
|
|
ErrInvalidAddress = 107, // Error: Invalid SAPI/TEI
|
|
ErrUnsupported = 108, // Error: Unsupported command. E.g. XID
|
|
ErrInvalidCR = 109, // Error: Invalid command/response flag
|
|
};
|
|
|
|
/**
|
|
* Codes used for TEI management procedures (Q.921 Table 8)
|
|
*/
|
|
enum TeiManagement {
|
|
TeiReq = 1, // TEI request (user to network)
|
|
TeiAssigned = 2, // TEI assigned (network to user)
|
|
TeiDenied = 3, // TEI denied (network to user)
|
|
TeiCheckReq = 4, // TEI check request (network to user)
|
|
TeiCheckRsp = 5, // TEI check response (user to network)
|
|
TeiRemove = 6, // TEI remove (network to user)
|
|
TeiVerify = 7 // TEI verify (user to network)
|
|
};
|
|
|
|
/**
|
|
* Frame category
|
|
*/
|
|
enum Category {
|
|
Data, // I, UI
|
|
Supervisory, // RR, RNR, REJ
|
|
Unnumbered, // SABME, DISC, UA DM, FRMR XID
|
|
Error
|
|
};
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~ISDNFrame();
|
|
|
|
/**
|
|
* Get the type of this frame
|
|
* @return The type of this frame as enumeration
|
|
*/
|
|
inline Type type() const
|
|
{ return m_type; }
|
|
|
|
/**
|
|
* Get the error type
|
|
* @return The error type of this frame as enumeration
|
|
*/
|
|
inline Type error() const
|
|
{ return m_error; }
|
|
|
|
/**
|
|
* Get the category of this frame
|
|
* @return The category of this frame as enumeration
|
|
*/
|
|
inline Category category() const
|
|
{ return m_category; }
|
|
|
|
/**
|
|
* Check if this frame is a command
|
|
* @return True if this frame is a command. False if it is a response
|
|
*/
|
|
inline bool command() const
|
|
{ return m_command; }
|
|
|
|
/**
|
|
* Get the SAPI of this frame
|
|
* @return The SAPI of this frame
|
|
*/
|
|
inline u_int8_t sapi() const
|
|
{ return m_sapi; }
|
|
|
|
/**
|
|
* Get the TEI of this frame
|
|
* @return The TEI of this frame
|
|
*/
|
|
inline u_int8_t tei() const
|
|
{ return m_tei; }
|
|
|
|
/**
|
|
* Check if this frame is a poll (expect response) or a final one
|
|
* @return True if this a poll frame. False if it is a final one
|
|
*/
|
|
inline bool poll() const
|
|
{ return m_poll; }
|
|
|
|
/**
|
|
* Get the transmitter send sequence number
|
|
* @return The transmitter send sequence number
|
|
*/
|
|
inline u_int8_t ns() const
|
|
{ return m_ns; }
|
|
|
|
/**
|
|
* Get the transmitter receive sequence number
|
|
* @return The transmitter receive sequence number
|
|
*/
|
|
inline u_int8_t nr() const
|
|
{ return m_nr; }
|
|
|
|
/**
|
|
* Get the length of the frame's header
|
|
* @return The length of the frame's header
|
|
*/
|
|
inline u_int8_t headerLength() const
|
|
{ return m_headerLength; }
|
|
|
|
/**
|
|
* Get the length of the data carried by this frame
|
|
* @return The length of the data carried by this frame
|
|
*/
|
|
inline u_int32_t dataLength() const
|
|
{ return m_dataLength; }
|
|
|
|
/**
|
|
* Get the frame's buffer
|
|
* @return The frame's buffer
|
|
*/
|
|
inline const DataBlock& buffer() const
|
|
{ return m_buffer; }
|
|
|
|
/**
|
|
* Check if the frame was sent
|
|
* @return True if the frame was sent
|
|
*/
|
|
inline bool sent() const
|
|
{ return m_sent; }
|
|
|
|
/**
|
|
* Set transmitted flag
|
|
*/
|
|
inline void sent(bool value)
|
|
{ m_sent = value; }
|
|
|
|
/**
|
|
* Get the text associated with the frame's type
|
|
* @return The text associated with the frame's type
|
|
*/
|
|
inline const char* name() const
|
|
{ return typeName(type()); }
|
|
|
|
/**
|
|
* Update sequence numbers for I frames
|
|
* @param ns Optional update send sequence number
|
|
* @param nr Optional update receive sequence number
|
|
*/
|
|
void update(u_int8_t* ns = 0, u_int8_t* nr = 0);
|
|
|
|
/**
|
|
* Get the data transferred with this frame
|
|
* @param dest The destination buffer
|
|
*/
|
|
inline void getData(DataBlock& dest) const
|
|
{ dest.assign((u_int8_t*)m_buffer.data() + m_headerLength,m_dataLength); }
|
|
|
|
/**
|
|
* Write this frame to a string for debug purposes
|
|
* @param dest The destination string
|
|
* @param extendedDebug True to dump message header and data
|
|
*/
|
|
void toString(String& dest, bool extendedDebug) const;
|
|
|
|
/**
|
|
* Check if the received frame is a TEI management frame
|
|
* @return True if the frame is a TEI management one, false if it's not
|
|
*/
|
|
bool checkTeiManagement() const;
|
|
|
|
/**
|
|
* Get reference number from frame
|
|
* @param data The data block which contains it
|
|
* @return Reference number
|
|
*/
|
|
static u_int16_t getRi(const DataBlock& data);
|
|
|
|
/**
|
|
* Get frame message type
|
|
* @param data The data block which contains it
|
|
* @return Message type
|
|
*/
|
|
inline static u_int8_t getType(const DataBlock& data)
|
|
{ return static_cast<u_int8_t>(data.at(3,0)); }
|
|
|
|
/**
|
|
* Get action indicator
|
|
* @param data Data block which contains it
|
|
* @return Action indicator value
|
|
*/
|
|
inline static u_int8_t getAi(const DataBlock& data)
|
|
{ return static_cast<u_int8_t>(data.at(4,0) >> 1); }
|
|
|
|
|
|
/**
|
|
* Parse a received data block
|
|
* @param data Data to parse
|
|
* @param receiver The receiver of the data
|
|
* @return ISDNFrame pointer or 0 (no control field)
|
|
*/
|
|
static ISDNFrame* parse(const DataBlock& data, ISDNLayer2* receiver);
|
|
|
|
/**
|
|
* Build a TEI management message buffer
|
|
* @param data Destination buffer to fill
|
|
* @param type The message type
|
|
* @param ri The reference number
|
|
* @param ai The action indicator
|
|
* @return True on succes
|
|
*/
|
|
static bool buildTeiManagement(DataBlock& data, u_int8_t type, u_int16_t ri,
|
|
u_int8_t ai);
|
|
|
|
/**
|
|
* Get the command bit value for a given side of a data link
|
|
* @param network True for the network side,
|
|
* false for the user side of a data link
|
|
* @return The appropriate command bit value
|
|
*/
|
|
static inline bool commandBit(bool network)
|
|
{ return network; }
|
|
|
|
/**
|
|
* Get the response bit value for a given side of a data link
|
|
* @param network True for the network side,
|
|
* false for the user side of a data link
|
|
* @return The appropriate response bit value
|
|
*/
|
|
static inline bool responseBit(bool network)
|
|
{ return !network; }
|
|
|
|
/**
|
|
* Get the command/response type from C/R bit value and sender type
|
|
* @param cr The value of the C/R bit
|
|
* @param sentByNetwork True if the sender is the network side of the data link
|
|
* @return True if it is a command
|
|
*/
|
|
static inline bool isCommand(u_int8_t cr, bool sentByNetwork)
|
|
{ return cr ? sentByNetwork : !sentByNetwork; }
|
|
|
|
/**
|
|
* Get the text associated with the given frame type
|
|
* @param type Frame type to get the text for
|
|
* @return The text associated with the given frame type
|
|
*/
|
|
static inline const char* typeName(Type type)
|
|
{ return lookup(type,s_types,"Invalid frame"); }
|
|
|
|
/**
|
|
* Keep the association between frame types and texts
|
|
*/
|
|
static TokenDict s_types[];
|
|
|
|
protected:
|
|
/**
|
|
* Constructor
|
|
* Used by the parser
|
|
* @param type Frame type
|
|
*/
|
|
ISDNFrame(Type type = Invalid);
|
|
|
|
/**
|
|
* Constructor
|
|
* Create U/S frames: SABME/DM/DISC/UA/FRMR/XID/RR/RNR/REJ
|
|
* Set data members. Encode frame in buffer according to Q.921
|
|
* Used by ISDNLayer2 to create outgoing frames
|
|
* @param type Frame type
|
|
* @param command Frame command/response's flag
|
|
* @param senderNetwork True if the sender is the network side of the data link
|
|
* @param sapi SAPI value
|
|
* @param tei TEI value
|
|
* @param pf Poll/final flag
|
|
* @param nr Optional transmitter receive sequence number
|
|
*/
|
|
ISDNFrame(Type type, bool command, bool senderNetwork,
|
|
u_int8_t sapi, u_int8_t tei, bool pf, u_int8_t nr = 0);
|
|
|
|
/**
|
|
* Constructor
|
|
* Create I/UI frames
|
|
* Set data members. Encode frame in buffer according to Q.921
|
|
* Used by ISDNLayer2 to create outgoing frames
|
|
* @param ack True to create an I frame. False to create an UI frame
|
|
* @param senderNetwork True if the sender is the network side of the data link
|
|
* @param sapi SAPI value
|
|
* @param tei TEI value
|
|
* @param pf Poll/final flag
|
|
* @param data Transmitted data
|
|
*/
|
|
ISDNFrame(bool ack, bool senderNetwork, u_int8_t sapi, u_int8_t tei,
|
|
bool pf, const DataBlock& data);
|
|
|
|
private:
|
|
Type m_type; // Frame type
|
|
Type m_error; // Frame error type
|
|
Category m_category; // Frame category
|
|
// Address
|
|
bool m_command; // Command/Response frame
|
|
bool m_senderNetwork; // True if the sender of this frame is the network side of the data link
|
|
u_int8_t m_sapi; // SAPI value
|
|
u_int8_t m_tei; // TEI value
|
|
// Control
|
|
bool m_poll; // Poll/Final flag
|
|
u_int8_t m_ns; // N(S) value (when applicable): transmitter send sequence number
|
|
u_int8_t m_nr; // N(R) value (when applicable): transmitter receive sequence number
|
|
// Data
|
|
u_int8_t m_headerLength; // Header length
|
|
u_int32_t m_dataLength; // Data length
|
|
DataBlock m_buffer; // Whole frame: header + data + FCS (frame check sequence = 2 bytes)
|
|
// Outgoing frames only
|
|
bool m_sent; // True if already sent
|
|
};
|
|
|
|
/**
|
|
* Q.921 ISDN Layer 2 implementation on top of a hardware HDLC interface
|
|
* @short ISDN Q.921 implementation on top of a hardware interface
|
|
*/
|
|
class YSIG_API ISDNQ921 : public ISDNLayer2, public SignallingReceiver, public SignallingDumpable
|
|
{
|
|
YCLASS2(ISDNQ921,ISDNLayer2,SignallingReceiver)
|
|
friend class ISDNQ921Management;
|
|
public:
|
|
/**
|
|
* Constructor
|
|
* Initialize this object and the component
|
|
* @param params Layer's and @ref TelEngine::ISDNLayer2 parameters
|
|
* @param name Name of this component
|
|
* @param mgmt TEI management component
|
|
* @param tei Value of TEI for this component
|
|
*/
|
|
ISDNQ921(const NamedList& params, const char* name = 0, ISDNQ921Management* mgmt = 0, u_int8_t tei = 0);
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~ISDNQ921();
|
|
|
|
/**
|
|
* Configure and initialize Q.921 and its interface
|
|
* @param config Optional configuration parameters override
|
|
* @return True if Q.921 and the interface were initialized properly
|
|
*/
|
|
virtual bool initialize(const NamedList* config);
|
|
|
|
/**
|
|
* Get the timeout of a data frame. After that, a higher layer may retransmit data
|
|
* @return The timeout of a data frame
|
|
*/
|
|
inline u_int64_t dataTimeout() const
|
|
{ return m_retransTimer.interval() * m_n200.maxVal(); }
|
|
|
|
/**
|
|
* Implements Q.921 DL-ESTABLISH and DL-RELEASE request primitives
|
|
* If accepted, the primitive is enqueued for further processing
|
|
* This method is thread safe
|
|
* @param tei This layer's TEI
|
|
* @param establish True to establish. False to release
|
|
* @param force True to establish even if we already are in this mode. This
|
|
* parameter is ignored if establish is false
|
|
* @return True if the request was accepted
|
|
*/
|
|
virtual bool multipleFrame(u_int8_t tei, bool establish, bool force);
|
|
|
|
/**
|
|
* Implements Q.921 DL-DATA and DL-UNIT DATA request primitives
|
|
* Send data through the HDLC interface
|
|
* This method is thread safe
|
|
* @param data Data to send
|
|
* @param tei The TEI to send with the data frane
|
|
* @param ack True to send an acknowledged frame, false to send an unacknowledged one
|
|
* @return False if the request was not accepted or send operation failed
|
|
*/
|
|
virtual bool sendData(const DataBlock& data, u_int8_t tei, bool ack);
|
|
|
|
/**
|
|
* Send a SABME frame to reset the layer
|
|
* @return True if a SABME frame was sent
|
|
*/
|
|
inline bool sendSabme()
|
|
{ return sendUFrame(ISDNFrame::SABME,true,true); }
|
|
|
|
/**
|
|
* Emergency release.
|
|
* Send 'disconnect' command. Reset all data. Set state to 'Released'
|
|
* This method is thread safe
|
|
*/
|
|
virtual void cleanup();
|
|
|
|
/**
|
|
* Set debug data of this layer
|
|
* @param printFrames Enable/disable frame printing on output
|
|
* @param extendedDebug Enable/disable hex data dump if print frames is enabled
|
|
*/
|
|
inline void setDebug(bool printFrames, bool extendedDebug)
|
|
{ m_extendedDebug = ((m_printFrames = printFrames) && extendedDebug); }
|
|
|
|
protected:
|
|
/**
|
|
* Detach links. Disposes memory
|
|
*/
|
|
virtual void destroyed()
|
|
{
|
|
ISDNLayer2::attach((ISDNLayer3*)0);
|
|
TelEngine::destruct(SignallingReceiver::attach(0));
|
|
SignallingComponent::destroyed();
|
|
}
|
|
|
|
/**
|
|
* Method called periodically to check timeouts
|
|
* This method is thread safe
|
|
* @param when Time to use as computing base for events and timeouts
|
|
*/
|
|
virtual void timerTick(const Time& when);
|
|
|
|
/**
|
|
* Process a packet received by the receiver's interface
|
|
* This method is thread safe
|
|
* @param packet The received packet
|
|
* @return True if message was successfully processed
|
|
*/
|
|
virtual bool receivedPacket(const DataBlock& packet);
|
|
|
|
/**
|
|
* Process the frame received
|
|
* @param frame Pointer to frame to process
|
|
* @return True if the frame was processed
|
|
*/
|
|
bool receivedFrame(ISDNFrame* frame);
|
|
|
|
/**
|
|
* Process a notification generated by the attached interface
|
|
* This method is thread safe
|
|
* @param event Notification event reported by the interface
|
|
* @return True if notification was processed
|
|
*/
|
|
virtual bool notify(SignallingInterface::Notification event);
|
|
|
|
/**
|
|
* Reset object if not in Released state. Drop all frames
|
|
* This method is thread safe
|
|
*/
|
|
void reset();
|
|
|
|
private:
|
|
virtual bool control(NamedList& params)
|
|
{ return SignallingDumpable::control(params,this); }
|
|
// Acknoledge outgoing frames
|
|
// @param frame The acknoledging frame
|
|
bool ackOutgoingFrames(const ISDNFrame* frame);
|
|
// Process a received I/UI frame
|
|
// @param ack True for I frame, false for UI frame
|
|
// @return True to send data to Layer 3
|
|
bool processDataFrame(const ISDNFrame* frame, bool ack);
|
|
// Process a received S frame
|
|
// @return True to exit from timer recovery state
|
|
bool processSFrame(const ISDNFrame* frame);
|
|
// Process a received U frame
|
|
// @param newState The new state if true is returned
|
|
// @param confirmation True if the new state is Established or Released and
|
|
// this is a confirmation
|
|
// @return True to change state
|
|
bool processUFrame(const ISDNFrame* frame, State& newState,
|
|
bool& confirmation);
|
|
// Accept frame according to Q.921 5.8.5
|
|
// Update counters.
|
|
// If not accepted the frame is rejected or dropped
|
|
// reject is set to true if the frame is rejected
|
|
bool acceptFrame(ISDNFrame* frame, bool& reject);
|
|
// Update rejected frames counter. Print message. Send FRMR (frame reject)
|
|
void rejectFrame(const ISDNFrame* frame, const char* reason = 0);
|
|
// Update dropped frames counter. Print message
|
|
void dropFrame(const ISDNFrame* frame, const char* reason = 0);
|
|
// Send S frames other then UI frames
|
|
bool sendUFrame(ISDNFrame::Type type, bool command, bool pf,
|
|
bool retrans = false);
|
|
// Send U frames
|
|
bool sendSFrame(ISDNFrame::Type type, bool command, bool pf);
|
|
// Send a frame to remote peer
|
|
// @param frame Frame to send
|
|
// @return False if the operation failed
|
|
bool sendFrame(const ISDNFrame* frame);
|
|
// Send pending outgoing I frames
|
|
// @param retrans: True Send all transmission window
|
|
// False Send only the unsent frames in transmission window
|
|
// @return True if a transmission took place
|
|
bool sendOutgoingData(bool retrans = false);
|
|
// Start/Stop T200. Stop/Start T203
|
|
// If start is false reset N200 (retransmission counter)
|
|
// @param start True to start. False to stop
|
|
// @param t203 Start/don't start T203. Ignored if start is false
|
|
// @param time Current time if known
|
|
void timer(bool start, bool t203, u_int64_t time = 0);
|
|
|
|
ISDNQ921Management* m_management; // TEI management component
|
|
// State variables
|
|
bool m_remoteBusy; // Remote peer is busy: don't send any I frames
|
|
bool m_timerRecovery; // T200 expired
|
|
bool m_rejectSent; // True if we've sent a REJ frame
|
|
bool m_pendingDMSabme; // True if we have a pending SABME on DM received
|
|
bool m_lastPFBit; // Last P/F bit sent with an I or S frame
|
|
u_int8_t m_vs; // Sequence number of the next transmitted I frame
|
|
u_int8_t m_va; // Last ack'd I frame by remote peer
|
|
u_int8_t m_vr; // Expected I frame sequence number
|
|
// Timers and counters
|
|
SignallingTimer m_retransTimer; // T200: Retransmission interval
|
|
SignallingTimer m_idleTimer; // T203: Channel idle interval
|
|
SignallingCounter m_window; // Maximum/current number of pending outgoing I frames
|
|
SignallingCounter m_n200; // Maximum/current retransmission counter
|
|
// Data
|
|
ObjList m_outFrames; // Outgoing I frames queue
|
|
// Statistics
|
|
u_int32_t m_txFrames; // The number of frames accepted by layer 1 to be transmitted
|
|
u_int32_t m_txFailFrames; // The number of frames not accepted by layer 1 to be transmitted
|
|
u_int32_t m_rxFrames; // The number of succesfully parsed frames
|
|
u_int32_t m_rxRejectedFrames; // The number of rejected frames. Doesn't include dropped frames
|
|
u_int32_t m_rxDroppedFrames; // The number of dropped frames. Doesn't include rejected frames
|
|
u_int32_t m_hwErrors; // The number of hardware notifications
|
|
// Debug flags
|
|
bool m_printFrames; // Print frames to output
|
|
bool m_extendedDebug; // Extended debug flag
|
|
// Flags used to avoid repetitive errors
|
|
bool m_errorSend; // Send error
|
|
bool m_errorReceive; // Receive error
|
|
};
|
|
|
|
/**
|
|
* This class is intended to be used as a proxy between an ISDN Layer 3 and multiple
|
|
* Layer 2 objects sharing the same signalling interface.
|
|
* It is used for BRI TEI management or PRI with D-channel backup.
|
|
* It also keeps a list of ISDN Layer 2 object(s) used for the designated purpose
|
|
* @short ISDN Layer 2 BRI TEI management or PRI with D-channel(s) backup
|
|
*/
|
|
class YSIG_API ISDNQ921Management : public ISDNLayer2, public ISDNLayer3, public SignallingReceiver, public SignallingDumpable
|
|
{
|
|
YCLASS3(ISDNQ921Management,ISDNLayer2,ISDNLayer3,SignallingReceiver)
|
|
public:
|
|
/**
|
|
* Constructor - initialize this Layer 2 and the component
|
|
* @param params Layer's parameters
|
|
* @param name Optional name of the component
|
|
* @param net True if managing the network side of Q.921
|
|
*/
|
|
ISDNQ921Management(const NamedList& params, const char* name = 0, bool net = true);
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~ISDNQ921Management();
|
|
|
|
/**
|
|
* Configure and initialize Q.921 Management and its children
|
|
* @param config Optional configuration parameters override
|
|
* @return True if Q.921 management was initialized properly
|
|
*/
|
|
virtual bool initialize(const NamedList* config);
|
|
|
|
/**
|
|
* Set the engine for this management and all Layer 2 children
|
|
* @param eng Pointer to the engine that will manage this mangement
|
|
*/
|
|
virtual void engine(SignallingEngine* eng);
|
|
|
|
/**
|
|
* Implements Q.921 DL-ESTABLISH and DL-RELEASE request primitives
|
|
* @param tei This layer TEI (-1 to apply it to all targets this object may have attached)
|
|
* @param establish True to establish. False to release
|
|
* @param force True to establish even if we already are established.
|
|
* @return True if the request was accepted
|
|
*/
|
|
virtual bool multipleFrame(u_int8_t tei, bool establish, bool force);
|
|
|
|
/**
|
|
* Implements Q.921 DL-DATA and DL-UNIT DATA request primitives
|
|
* @param data Data to send
|
|
* @param tei This layer TEI (-1 for broadcast)
|
|
* @param ack True to send an acknowledged frame, false to send an unacknowledged one
|
|
* @return True if the request was accepted
|
|
*/
|
|
virtual bool sendData(const DataBlock& data, u_int8_t tei, bool ack);
|
|
|
|
/**
|
|
* Implements Q.921 send frame to the interface
|
|
* @param frame The frame to be sent
|
|
* @param q921 Pointer to the Q.921 that sends the frame, if any
|
|
* @return True if the frame was sent
|
|
*/
|
|
bool sendFrame(const ISDNFrame* frame, const ISDNQ921* q921 = 0);
|
|
|
|
|
|
/**
|
|
* Emergency release.
|
|
* Cleanup all Layer 2 objects attached to this Management
|
|
*/
|
|
virtual void cleanup();
|
|
|
|
/**
|
|
* Implements Q.921 DL-ESTABLISH indication/confirmation primitive:
|
|
* 'multiple frame acknowledged' mode established
|
|
* @param tei This layer TEI
|
|
* @param confirm True if this is a confirmation of a previous request,
|
|
* false if it is an indication of state change on remote request
|
|
* @param timeout True if the reason is a timeout
|
|
* @param layer2 Pointer to the notifier
|
|
*/
|
|
virtual void multipleFrameEstablished(u_int8_t tei, bool confirm, bool timeout, ISDNLayer2* layer2);
|
|
|
|
/**
|
|
* Implements Q.921 DL-RELEASE indication/confirmation primitive:
|
|
* 'multiple frame acknowledged' mode released
|
|
* @param tei This layer TEI
|
|
* @param confirm True if this is a confirmation of a previous request,
|
|
* false if it is an indication of state change on remote request
|
|
* @param timeout True if the reason is a timeout.
|
|
* @param layer2 Pointer to the notifier
|
|
*/
|
|
virtual void multipleFrameReleased(u_int8_t tei, bool confirm, bool timeout, ISDNLayer2* layer2);
|
|
|
|
/**
|
|
* Notification from layer 2 of data link set/release command or response
|
|
* Used for stateless layer 2
|
|
* @param tei This layer TEI
|
|
* @param cmd True if received a command, false if received a response
|
|
* @param value The value of the notification
|
|
* If 'cmd' is true (command), the value is true if a request to establish data link was received
|
|
* or false if received a request to release data link
|
|
* If 'cmd' is false (response), the value is the response
|
|
* @param layer2 Pointer to the notifier
|
|
*/
|
|
virtual void dataLinkState(u_int8_t tei, bool cmd, bool value, ISDNLayer2* layer2);
|
|
|
|
/**
|
|
* Implements Q.921 DL-DATA and DL-UNIT DATA indication primitives
|
|
* Receive data from an encapsulated Layer 2 and send it to the attached Layer 3
|
|
* @param data Received data
|
|
* @param tei The TEI as received in the packet
|
|
* @param layer2 Pointer to the sender
|
|
*/
|
|
virtual void receiveData(const DataBlock& data, u_int8_t tei, ISDNLayer2* layer2);
|
|
|
|
protected:
|
|
/**
|
|
* Method called periodically to check timeouts
|
|
* This method is thread safe
|
|
* @param when Time to use as computing base for events and timeouts
|
|
*/
|
|
virtual void timerTick(const Time& when);
|
|
|
|
/**
|
|
* Process a Signalling Packet received by the interface.
|
|
* Parse the data and send all non-UI frames to the appropriate Layer 2.
|
|
* Process UI frames
|
|
* @return True if message was successfully processed
|
|
*/
|
|
virtual bool receivedPacket(const DataBlock& packet);
|
|
|
|
/**
|
|
* Process a notification generated by the attached interface
|
|
* @param event Notification event reported by the interface
|
|
* @return True if notification was processed
|
|
*/
|
|
virtual bool notify(SignallingInterface::Notification event);
|
|
|
|
/**
|
|
* Process UI frames carrying TEI management messages
|
|
* @param frame The parsed frame
|
|
* @return False if the frame is not a TEI management one, true otherwise
|
|
*/
|
|
bool processTeiManagement(ISDNFrame* frame);
|
|
|
|
/**
|
|
* Send a TEI management frame
|
|
* @param type Type of the frame to send
|
|
* @param ri Reference number to send in frame
|
|
* @param ai Action indicator to send in frame
|
|
* @param tei The TEI to send the frame to, default use broadcast
|
|
* @param pf The Poll/Final bit to set in the frame
|
|
* @return True if frame was sent successfully
|
|
*/
|
|
bool sendTeiManagement(ISDNFrame::TeiManagement type, u_int16_t ri, u_int8_t ai, u_int8_t tei = 127, bool pf = false);
|
|
|
|
/**
|
|
* Process TEI request message and send back to TE:
|
|
* TEI Assigned message if the request succeeded;
|
|
* TEI Denied message with the received reference number if the
|
|
* reference number is already in use;
|
|
* TEI Denied message with the reference number set to 127 if
|
|
* there is no TEI value available.
|
|
* @param ri The reference number
|
|
* @param ai Action indicator
|
|
* @param pf The Poll/Final bit in the incoming frame
|
|
*/
|
|
void processTeiRequest(u_int16_t ri, u_int8_t ai, bool pf);
|
|
|
|
/**
|
|
* Process Tei remove message removing the tei(s) contained by ai
|
|
* @param ai Contains the TEI value to remove or 127 to remove all TEI values
|
|
*/
|
|
void processTeiRemove(u_int8_t ai);
|
|
|
|
/**
|
|
* Process TEI Check Request message and send to the NET a message with
|
|
* the TEI and the asociated reference number
|
|
* @param ai Contains the TEI value to check or 127 to check all TEI values
|
|
* @param pf The Poll/Final bit in the incoming frame
|
|
*/
|
|
void processTeiCheckRequest(u_int8_t ai, bool pf);
|
|
|
|
/**
|
|
* Process TEI Check Response message and set the check flag to true to know that we have a response for that TEI
|
|
* @param ri The associated reference number to the ai
|
|
* @param ai The TEI value as received in the answer
|
|
*/
|
|
void processTeiCheckResponse(u_int16_t ri, u_int8_t ai);
|
|
|
|
/**
|
|
* Process TEI Assigned message
|
|
* @param ri The reference number assigned to the ai
|
|
* @param ai The TEI value assigned
|
|
*/
|
|
void processTeiAssigned(u_int16_t ri, u_int8_t ai);
|
|
|
|
/**
|
|
* Process TEI Denied message
|
|
* @param ri The reference number of the denied request
|
|
*/
|
|
void processTeiDenied(u_int16_t ri);
|
|
|
|
/**
|
|
* Process TEI verify
|
|
* @param ai The TEI value of the message initiator
|
|
* @param pf The Poll/Final bit in the incoming frame
|
|
*/
|
|
void processTeiVerify(u_int8_t ai, bool pf);
|
|
|
|
/**
|
|
* Send TEI request message
|
|
* @param tei TEI value to assign
|
|
*/
|
|
void sendTeiReq(u_int8_t tei);
|
|
|
|
/**
|
|
* Send a TEI remove frame
|
|
*/
|
|
void sendTeiRemove();
|
|
|
|
private:
|
|
ISDNQ921* m_layer2[127]; // The list of Layer 2 objects attached to this Layer 3
|
|
SignallingTimer m_teiManTimer; // T202
|
|
SignallingTimer m_teiTimer; // T201
|
|
};
|
|
|
|
/**
|
|
* Q.921 ISDN Layer 2 pasive (stateless) implementation on top of a hardware HDLC interface
|
|
* @short Stateless pasive ISDN Q.921 implementation on top of a hardware interface
|
|
*/
|
|
class YSIG_API ISDNQ921Passive : public ISDNLayer2, public SignallingReceiver, public SignallingDumpable
|
|
{
|
|
YCLASS2(ISDNQ921Passive,ISDNLayer2,SignallingReceiver)
|
|
public:
|
|
/**
|
|
* Constructor
|
|
* Initialize this object and the component
|
|
* @param params Layer's and @ref TelEngine::ISDNLayer2 parameters
|
|
* @param name Name of this component
|
|
*/
|
|
ISDNQ921Passive(const NamedList& params, const char* name = 0);
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~ISDNQ921Passive();
|
|
|
|
/**
|
|
* Emergency release
|
|
* Reset all data. Set state to 'Released'
|
|
* This method is thread safe
|
|
*/
|
|
virtual void cleanup();
|
|
|
|
/**
|
|
* Configure and initialize the passive Q.921 and its interface
|
|
* @param config Optional configuration parameters override
|
|
* @return True if Q.921 and the interface were initialized properly
|
|
*/
|
|
virtual bool initialize(const NamedList* config);
|
|
|
|
/**
|
|
* Set debug data of this layer
|
|
* @param printFrames Enable/disable frame printing on output
|
|
* @param extendedDebug Enable/disable hex data dump if print frames is enabled
|
|
*/
|
|
inline void setDebug(bool printFrames, bool extendedDebug)
|
|
{ m_extendedDebug = ((m_printFrames = printFrames) && extendedDebug); }
|
|
|
|
protected:
|
|
/**
|
|
* Detach links. Disposes memory
|
|
*/
|
|
virtual void destroyed()
|
|
{
|
|
ISDNLayer2::attach(0);
|
|
TelEngine::destruct(SignallingReceiver::attach(0));
|
|
SignallingComponent::destroyed();
|
|
}
|
|
|
|
/**
|
|
* Method called periodically to check timeouts
|
|
* This method is thread safe
|
|
* @param when Time to use as computing base for events and timeouts
|
|
*/
|
|
virtual void timerTick(const Time& when);
|
|
|
|
/**
|
|
* Process a packet received by the receiver's interface
|
|
* This method is thread safe
|
|
* @param packet The received packet
|
|
* @return True if message was successfully processed
|
|
*/
|
|
virtual bool receivedPacket(const DataBlock& packet);
|
|
|
|
/**
|
|
* Process a notification generated by the attached interface
|
|
* This method is thread safe
|
|
* @param event Notification event reported by the interface
|
|
* @return True if notification was processed
|
|
*/
|
|
virtual bool notify(SignallingInterface::Notification event);
|
|
|
|
private:
|
|
virtual bool control(NamedList& params)
|
|
{ return SignallingDumpable::control(params,this); }
|
|
// Filter received frames. Accept only frames that would generate a notification to the upper layer:
|
|
// UI/I, and Valid SABME/DISC/UA/DM
|
|
// On success, if frame is not a data one, prepare cmd and value to notify layer 3
|
|
bool acceptFrame(ISDNFrame* frame, bool& cmd, bool& value);
|
|
// Show debug message. Count dropped frames
|
|
bool dropFrame(const ISDNFrame* frame, const char* reason = 0);
|
|
|
|
bool m_checkLinkSide; // Check if this is the correct side of the data link
|
|
SignallingTimer m_idleTimer; // Channel idle interval
|
|
u_int8_t m_lastFrame; // Transmitter send number of the last received frame
|
|
u_int32_t m_rxFrames; // The number of succesfully parsed frames
|
|
u_int32_t m_rxRejectedFrames; // The number of rejected frames. Doesn't include dropped frames
|
|
u_int32_t m_rxDroppedFrames; // The number of dropped frames. Doesn't include rejected frames
|
|
u_int32_t m_hwErrors; // The number of hardware notifications
|
|
bool m_printFrames; // Print frames to output
|
|
bool m_extendedDebug; // Extended debug flag
|
|
bool m_errorReceive; // Receive error
|
|
};
|
|
|
|
/**
|
|
* RFC4233 ISDN Layer 2 implementation over SCTP/IP
|
|
* IUA is intended to be used as a Provider-User where Q.921 runs on a
|
|
* Signalling Gateway and the user (Q.931) runs on an Application Server.
|
|
* @short SIGTRAN ISDN Q.921 User Adaptation Layer
|
|
*/
|
|
class YSIG_API ISDNIUA : public ISDNLayer2, public SIGTRAN
|
|
{
|
|
YCLASS(ISDNIUA,ISDNLayer2)
|
|
protected:
|
|
/**
|
|
* Constructor
|
|
* Initialize this object and the layer 2
|
|
* @param params Object and Layer 2 parameters
|
|
* @param name Optional name for Layer 2
|
|
*/
|
|
inline ISDNIUA(const NamedList& params, const char* name = 0)
|
|
: ISDNLayer2(params,name)
|
|
{ }
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~ISDNIUA()
|
|
{ }
|
|
};
|
|
|
|
/**
|
|
* Q.931 ISDN Layer 3 message Information Element
|
|
* @short A Q.931 ISDN Layer 3 message Information Element
|
|
*/
|
|
class YSIG_API ISDNQ931IE : public NamedList
|
|
{
|
|
friend class ISDNQ931Message;
|
|
public:
|
|
/**
|
|
* Keep IE type enumerations. See Q.931 4.5
|
|
*/
|
|
enum Type {
|
|
// Fixed (1 byte) length information element
|
|
Shift = 0x90, // Shift
|
|
MoreData = 0xa0, // More data
|
|
SendComplete = 0xa1, // Sending complete
|
|
Congestion = 0xb0, // Congestion level
|
|
Repeat = 0xd0, // Repeat indicator
|
|
// Variable length information element
|
|
Segmented = 0x00, // Segmented message
|
|
BearerCaps = 0x04, // Bearer capability
|
|
Cause = 0x08, // Cause
|
|
CallIdentity = 0x10, // Call identity
|
|
CallState = 0x14, // Call state
|
|
ChannelID = 0x18, // Channel identification
|
|
Progress = 0x1e, // Progress indicator
|
|
NetFacility = 0x20, // Network-specific facilities
|
|
Notification = 0x27, // Notification indicator
|
|
Display = 0x28, // Display
|
|
DateTime = 0x29, // Date/time
|
|
Keypad = 0x2c, // Keypad facility
|
|
Signal = 0x34, // Signal
|
|
ConnectedNo = 0x4c, // Connected number (Q.951)
|
|
CallingNo = 0x6c, // Calling party number
|
|
CallingSubAddr = 0x6d, // Calling party subaddress
|
|
CalledNo = 0x70, // Called party number
|
|
CalledSubAddr = 0x71, // Called party subaddress
|
|
NetTransit = 0x78, // Transit network selection
|
|
Restart = 0x79, // Restart indicator
|
|
LoLayerCompat = 0x7c, // Low layer compatibility
|
|
HiLayerCompat = 0x7d, // High layer compatibility
|
|
// Not used
|
|
UserUser = 0x7e, // User-user
|
|
Escape = 0x7f, // Escape for extension
|
|
};
|
|
|
|
/**
|
|
* Constructor
|
|
* Constructs an unknown IE with raw data
|
|
* @param type The type of this IE
|
|
*/
|
|
ISDNQ931IE(u_int16_t type);
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~ISDNQ931IE();
|
|
|
|
/**
|
|
* Get the type of this IE
|
|
* @return The type of this IE
|
|
*/
|
|
inline u_int8_t type() const
|
|
{ return (u_int8_t)m_type; }
|
|
|
|
/**
|
|
* Add a parameter using the IE name as prefix
|
|
* @param name Parameter name
|
|
* @param value Parameter value
|
|
*/
|
|
inline void addParamPrefix(const char* name, const char* value)
|
|
{ addParam(*this+"."+name,value); }
|
|
|
|
/**
|
|
* Put this message into a string for debug purposes
|
|
* @param dest The destination string
|
|
* @param extendedDebug True to add the content of this IE and dump data.
|
|
* If false, only the IE name is added to the destination string
|
|
* @param before Optional string to be added before
|
|
*/
|
|
void toString(String& dest, bool extendedDebug, const char* before = 0);
|
|
|
|
/**
|
|
* Get the string associated with a given IE type
|
|
* @param type The IE type whose string we want to get
|
|
* @param defVal The value to return if not found
|
|
* @return Pointer to the requested string or defValue
|
|
*/
|
|
static inline const char* typeName(int type, const char* defVal = 0)
|
|
{ return lookup(type,s_type,defVal); }
|
|
|
|
/**
|
|
* Keep the string associated with IE types
|
|
*/
|
|
static TokenDict s_type[];
|
|
|
|
/**
|
|
* Internally used buffer
|
|
*/
|
|
DataBlock m_buffer;
|
|
|
|
private:
|
|
u_int16_t m_type; // IE type
|
|
};
|
|
|
|
/**
|
|
* Q.931 ISDN Layer 3 message
|
|
* @short A Q.931 ISDN Layer 3 message
|
|
*/
|
|
class YSIG_API ISDNQ931Message : public SignallingMessage
|
|
{
|
|
public:
|
|
/**
|
|
* Message type enumeration
|
|
*/
|
|
enum Type {
|
|
Alerting = 0x01, // ALERTING
|
|
Proceeding = 0x02, // CALL PROCEEDING
|
|
Connect = 0x07, // CONNECT
|
|
ConnectAck = 0x0f, // CONNECT ACK
|
|
Progress = 0x03, // PROGRESS
|
|
Setup = 0x05, // SETUP
|
|
SetupAck = 0x0d, // SETUP ACK
|
|
Resume = 0x26, // RESUME
|
|
ResumeAck = 0x2e, // RESUME ACK
|
|
ResumeRej = 0x22, // RESUME REJECT
|
|
Suspend = 0x25, // SUSPEND
|
|
SuspendAck = 0x2d, // SUSPEND ACK
|
|
SuspendRej = 0x21, // SUSPEND REJECT
|
|
UserInfo = 0x20, // USER INFO
|
|
Disconnect = 0x45, // DISCONNECT
|
|
Release = 0x4d, // RELEASE
|
|
ReleaseComplete = 0x5a, // RELEASE COMPLETE
|
|
Restart = 0x46, // RESTART
|
|
RestartAck = 0x4e, // RESTART ACK
|
|
Segment = 0x60, // SEGMENT
|
|
CongestionCtrl = 0x79, // CONGESTION CONTROL
|
|
Info = 0x7b, // INFORMATION
|
|
Notify = 0x6e, // NOTIFY
|
|
Status = 0x7d, // STATUS
|
|
StatusEnquiry = 0x75, // STATUS ENQUIRY
|
|
};
|
|
|
|
/**
|
|
* Constructor
|
|
* Constructs a message from given data. Used for incoming messages
|
|
* @param type Message type
|
|
* @param initiator The call initiator flag: True: this is the initiator
|
|
* @param callRef The call reference
|
|
* @param callRefLen The call reference length
|
|
*/
|
|
ISDNQ931Message(Type type, bool initiator, u_int32_t callRef, u_int8_t callRefLen);
|
|
|
|
/**
|
|
* Constructor
|
|
* Constructs a message with dummy call reference
|
|
* @param type Message type
|
|
*/
|
|
ISDNQ931Message(Type type);
|
|
|
|
/**
|
|
* Constructor
|
|
* Constructs a message for a given call. Used for outgoing messages
|
|
* @param type Message type
|
|
* @param call The call this message belongs to
|
|
*/
|
|
ISDNQ931Message(Type type, ISDNQ931Call* call);
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~ISDNQ931Message();
|
|
|
|
/**
|
|
* Get the type of this message
|
|
* @return The type of this message as enumeration
|
|
*/
|
|
inline Type type() const
|
|
{ return m_type; }
|
|
|
|
/**
|
|
* Check if the sender of this message is the call initiator
|
|
* @return True if the sender of this message is the call initiator
|
|
*/
|
|
inline bool initiator() const
|
|
{ return m_initiator; }
|
|
|
|
/**
|
|
* Get the id of the call this message belongs to
|
|
* @return The call reference
|
|
*/
|
|
inline u_int32_t callRef() const
|
|
{ return m_callRef; }
|
|
|
|
/**
|
|
* Get the length of the call reference
|
|
* @return The length of the call reference
|
|
*/
|
|
inline u_int8_t callRefLen() const
|
|
{ return m_callRefLen; }
|
|
|
|
/**
|
|
* Check if this message has a dummy call reference
|
|
* @return True if this message has a dummy call reference
|
|
*/
|
|
inline bool dummyCallRef() const
|
|
{ return m_dummy; }
|
|
|
|
/**
|
|
* Check if this message contains unknown mandatory IE(s)
|
|
* @return True if this message contains unknown mandatory IE(s)
|
|
*/
|
|
inline bool unknownMandatory() const
|
|
{ return m_unkMandatory; }
|
|
|
|
/**
|
|
* Set the unknown mandatory IE(s) flag
|
|
*/
|
|
inline void setUnknownMandatory()
|
|
{ m_unkMandatory = true; }
|
|
|
|
/**
|
|
* Get the IE list of this message
|
|
* @return A valid pointer to the list of this message's IEs
|
|
*/
|
|
inline ObjList* ieList()
|
|
{ return &m_ie; }
|
|
|
|
/**
|
|
* Get a pointer to the first IE with the given type
|
|
* @param type Requested IE's type
|
|
* @param base Optional search starting element. If 0, search is started from the first IE following base
|
|
* @return Pointer to the IE or 0 if not found
|
|
*/
|
|
ISDNQ931IE* getIE(ISDNQ931IE::Type type, ISDNQ931IE* base = 0);
|
|
|
|
/**
|
|
* Remove an IE from list without destroying it
|
|
* @param type Requested IE's type
|
|
* @param base Optional search starting element. If 0, search is started from the first IE following base
|
|
* @return Pointer to the IE or 0 if not found
|
|
*/
|
|
ISDNQ931IE* removeIE(ISDNQ931IE::Type type, ISDNQ931IE* base = 0);
|
|
|
|
/**
|
|
* Get the value of a given parameter of a given IE
|
|
* @param type Requested IE's type
|
|
* @param param Requested IE's parameter. Set to 0 to use IE's name
|
|
* @param defVal Default value to return if IE is missing or the parameter is missing
|
|
* @return Pointer to the requested value or 0
|
|
*/
|
|
inline const char* getIEValue(ISDNQ931IE::Type type, const char* param,
|
|
const char* defVal = 0)
|
|
{
|
|
ISDNQ931IE* ie = getIE(type);
|
|
return (ie ? ie->getValue(param?param:ie->c_str(),defVal) : defVal);
|
|
}
|
|
|
|
/**
|
|
* Append an IE with a given parameter
|
|
* @param type IE's type
|
|
* @param param IE's parameter. Set to 0 to use IE's name
|
|
* @param value IE parameter's value
|
|
* @return Pointer to the requested value or 0
|
|
*/
|
|
inline ISDNQ931IE* appendIEValue(ISDNQ931IE::Type type, const char* param,
|
|
const char* value)
|
|
{
|
|
ISDNQ931IE* ie = new ISDNQ931IE(type);
|
|
ie->addParam(param?param:ie->c_str(),value);
|
|
appendSafe(ie);
|
|
return ie;
|
|
}
|
|
|
|
/**
|
|
* Append an information element to this message
|
|
* @param ie Information element to add
|
|
* @return True if the IE was added or replaced, false if it was invalid
|
|
*/
|
|
inline bool append(ISDNQ931IE* ie)
|
|
{ return 0 != m_ie.append(ie); }
|
|
|
|
/**
|
|
* Append/insert an information element to this message. Check the IE list consistency
|
|
* The given IE is 'consumed': deleted or appended to the list
|
|
* @param ie Information element to add
|
|
* @return True if the IE was added or replaced, false if it was invalid
|
|
*/
|
|
bool appendSafe(ISDNQ931IE* ie);
|
|
|
|
/**
|
|
* Put this message into a string for debug purposes
|
|
* @param dest The destination string
|
|
* @param extendedDebug True to add the content of IEs and dump data.
|
|
* If false, only the IE name is added to the destination string
|
|
* @param indent The line indent
|
|
*/
|
|
void toString(String& dest, bool extendedDebug, const char* indent = 0) const;
|
|
|
|
/**
|
|
* Get a pointer to a data member or this message
|
|
* @param name Object name
|
|
* @return The requested pointer or 0 if not exists
|
|
*/
|
|
virtual void* getObject(const String& name) const;
|
|
|
|
/**
|
|
* Encode this message
|
|
* If message segmentation is allowed and the message is longer then maximum allowed,
|
|
* split it into Segment messages
|
|
* @param parserData The parser settings
|
|
* @param dest The destination list.
|
|
* If 1 is returned the list contains a DataBuffer with this message.
|
|
* If more then 1 is returned, the list is filled with data buffers with Segment messages
|
|
* @return The number of segments on success or 0 on failure.
|
|
*/
|
|
u_int8_t encode(ISDNQ931ParserData& parserData, ObjList& dest);
|
|
|
|
/**
|
|
* Parse received data
|
|
* If the message type is Segment, decode only the header and the first IE
|
|
* If valid, fills the given buffer with the rest of the message. If segData is 0, drop the message.
|
|
* @param parserData The parser settings
|
|
* @param buffer The received data
|
|
* @param segData Segment message data. If 0, received segmented messages will be dropped
|
|
* @return Valid ISDNQ931Message pointer on success or 0
|
|
*/
|
|
static ISDNQ931Message* parse(ISDNQ931ParserData& parserData,
|
|
const DataBlock& buffer, DataBlock* segData);
|
|
|
|
/**
|
|
* Get the string associated with a given message type
|
|
* @param t The message type whose string we want to get
|
|
* @return Pointer to the string associated with the given message type or 0
|
|
*/
|
|
static inline const char* typeName(int t)
|
|
{ return lookup(t,s_type,"Unknown"); }
|
|
|
|
/**
|
|
* Keep the string associated with message types
|
|
*/
|
|
static TokenDict s_type[];
|
|
|
|
/**
|
|
* Internally used buffer for debug purposes
|
|
*/
|
|
DataBlock m_buffer;
|
|
|
|
private:
|
|
Type m_type; // Message type
|
|
bool m_initiator; // The call initiator flag: True: this is the initiator
|
|
u_int32_t m_callRef; // The call reference
|
|
u_int8_t m_callRefLen; // The call reference length
|
|
bool m_unkMandatory; // True if this message contains unknown mandatory IE(s)
|
|
bool m_dummy; // True if this message has a dummy call reference
|
|
ObjList m_ie; // IE list
|
|
};
|
|
|
|
/**
|
|
* Extract data from IEs. Append IEs to Q.931 messages
|
|
* @short A Q.931 message IE data processor
|
|
*/
|
|
class YSIG_API ISDNQ931IEData
|
|
{
|
|
friend class ISDNQ931Call;
|
|
friend class ISDNQ931CallMonitor;
|
|
friend class ISDNQ931;
|
|
friend class ISDNQ931Monitor;
|
|
private:
|
|
// Constructor
|
|
ISDNQ931IEData(bool bri = false);
|
|
// Process received IEs
|
|
// If add is true, append an IE to the message
|
|
// If add is false, extract data from message. Set data to default values if IE is missing
|
|
// @return False if the IE is missing when decoding or the IE wasn't added
|
|
bool processBearerCaps(ISDNQ931Message* msg, bool add, ISDNQ931ParserData* data = 0);
|
|
bool processCause(ISDNQ931Message* msg, bool add, ISDNQ931ParserData* data = 0);
|
|
bool processDisplay(ISDNQ931Message* msg, bool add, ISDNQ931ParserData* data = 0);
|
|
bool processKeypad(ISDNQ931Message* msg, bool add, ISDNQ931ParserData* data = 0);
|
|
bool processChannelID(ISDNQ931Message* msg, bool add, ISDNQ931ParserData* data = 0);
|
|
bool processProgress(ISDNQ931Message* msg, bool add, ISDNQ931ParserData* data = 0);
|
|
bool processRestart(ISDNQ931Message* msg, bool add, ISDNQ931ParserData* data = 0);
|
|
bool processNotification(ISDNQ931Message* msg, bool add, ISDNQ931ParserData* data = 0);
|
|
bool processCalledNo(ISDNQ931Message* msg, bool add, ISDNQ931ParserData* data = 0);
|
|
bool processCallingNo(ISDNQ931Message* msg, bool add, ISDNQ931ParserData* data = 0);
|
|
|
|
// IE parameters
|
|
String m_display; // Display: The data
|
|
String m_callerNo; // CallingNo: Number
|
|
String m_callerType; // CallingNo: Number type
|
|
String m_callerPlan; // CallingNo: Number plan
|
|
String m_callerPres; // CallingNo: Number presentation
|
|
String m_callerScreening; // CallingNo: Number screening
|
|
String m_calledNo; // CalledNo: Number
|
|
String m_calledType; // CalledNo: Number type
|
|
String m_calledPlan; // CalledNo: Number plan
|
|
String m_transferCapability; // BearerCaps: Transfer capability
|
|
String m_transferMode; // BearerCaps: Transfer mode
|
|
String m_transferRate; // BearerCaps: Transfer rate
|
|
String m_format; // BearerCaps: Layer 1 protocol
|
|
String m_reason; // Cause
|
|
String m_keypad; // Keypad: 'keypad' parameter
|
|
String m_progress; // Progress: Progress description
|
|
String m_notification; // Notify: Notification indicator
|
|
bool m_bri; // ChannelID: BRI interface flag
|
|
bool m_channelMandatory; // ChannelID: Indicated channel is mandatory/preferred
|
|
bool m_channelByNumber; // ChannelID: m_channels contains a channel list or a slot map
|
|
String m_channelType; // ChannelID: Channel type
|
|
String m_channelSelect; // ChannelID: Channel select
|
|
String m_channels; // ChannelID: Channel list or slot map
|
|
String m_restart; // Restart: The class of restarting circuits
|
|
};
|
|
|
|
/**
|
|
* Q.931 ISDN call and call controller state
|
|
* @short Q.931 ISDN call and call controller state
|
|
*/
|
|
class YSIG_API ISDNQ931State
|
|
{
|
|
public:
|
|
/**
|
|
* Call and call controller state enumeration values
|
|
*/
|
|
enum State {
|
|
// Common state
|
|
Null = 0x00, // Null
|
|
// Call states
|
|
CallInitiated = 0x01, // Call initiated: sent SETUP
|
|
OverlapSend = 0x02, // Overlap sending
|
|
OutgoingProceeding = 0x03, // Outgoing call proceeding: received valid CALL PROCEEDING
|
|
CallDelivered = 0x04, // Call delivered: received valid ALERTING
|
|
CallPresent = 0x06, // Call present: received valid SETUP or recover from STATUS
|
|
CallReceived = 0x07, // Call received: sent ALERTING or recover from STATUS
|
|
ConnectReq = 0x08, // Connect request: sent/received valid CONNECT or recover from STATUS
|
|
IncomingProceeding = 0x09, // Incoming call proceeding: sent CALL PROCEEDING or recover from STATUS
|
|
Active = 0x0a, // Active: sent/received valid CONNECT ACK
|
|
DisconnectReq = 0x0b, // Disconnect request: sent DISCONNECT
|
|
DisconnectIndication = 0x0c, // Disconnect indication: received valid DISCONNECT
|
|
SuspendReq = 0x0f, // Suspend request
|
|
ResumeReq = 0x11, // Resume reques
|
|
ReleaseReq = 0x13, // Release request: sent/received valid RELEASE
|
|
CallAbort = 0x16, // Call abort: received STATUS in Null state with remote not in Null state
|
|
OverlapRecv = 0x19, // Overlap receiving
|
|
// Call controller states
|
|
RestartReq = 0x3d, // Restart request
|
|
Restart = 0x3e, // Restart
|
|
};
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
inline ISDNQ931State() : m_state(Null)
|
|
{ }
|
|
|
|
/**
|
|
* Get the state
|
|
* @return The state as enumeration
|
|
*/
|
|
inline State state() const
|
|
{ return m_state; }
|
|
|
|
/**
|
|
* Get the text associated with a given state value
|
|
* @param s The requested state value
|
|
* @return The text associated with the given state value or 0
|
|
*/
|
|
static const char* stateName(u_int8_t s)
|
|
{ return lookup(s,s_states,0); }
|
|
|
|
/**
|
|
* Keep the association between state values and their texts
|
|
*/
|
|
static TokenDict s_states[];
|
|
|
|
protected:
|
|
/**
|
|
* Check if a received message type is valid in the current call state
|
|
* @param type The type of the received message
|
|
* @param retrans Optional flag to set on failure if the message is a retransmission
|
|
* @return False if the message is not valid in the current call state
|
|
*/
|
|
bool checkStateRecv(int type, bool* retrans);
|
|
|
|
/**
|
|
* Check if a message is allowed to be sent in the current call state
|
|
* @param type The type of the received message
|
|
* @return False if the message is not valid in the current call state
|
|
*/
|
|
bool checkStateSend(int type);
|
|
|
|
/**
|
|
* The call and call controller state
|
|
*/
|
|
State m_state;
|
|
|
|
};
|
|
|
|
/**
|
|
* Q.931 ISDN call
|
|
* @short A Q.931 ISDN call
|
|
*/
|
|
class YSIG_API ISDNQ931Call : public ISDNQ931State, public SignallingCall
|
|
{
|
|
friend class ISDNQ931;
|
|
public:
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~ISDNQ931Call();
|
|
|
|
/**
|
|
* Get the id of this call
|
|
* @return The call reference
|
|
*/
|
|
inline u_int32_t callRef() const
|
|
{ return m_callRef; }
|
|
|
|
/**
|
|
* Get the length of the call reference
|
|
* @return The length of the call reference
|
|
*/
|
|
inline u_int32_t callRefLen() const
|
|
{ return m_callRefLen; }
|
|
|
|
/**
|
|
* Get the Terminal Equipment Indicator for this call
|
|
* @return Value of TEI used in this call
|
|
*/
|
|
inline u_int8_t callTei() const
|
|
{ return m_tei; }
|
|
|
|
/**
|
|
* Get the circuit this call had reserved
|
|
* @return The circuit reserved by this call
|
|
*/
|
|
inline SignallingCircuit* circuit()
|
|
{ return m_circuit; }
|
|
|
|
/**
|
|
* Set termination (and destroy) flags
|
|
* This method is thread safe
|
|
* @param destroy The destroy flag. If true, the call will be destroyed
|
|
* @param reason Terminate reason
|
|
*/
|
|
void setTerminate(bool destroy, const char* reason);
|
|
|
|
/**
|
|
* Send an event to this call
|
|
* This method is thread safe
|
|
* @param event The sent event
|
|
* @return True if the operation succedded
|
|
*/
|
|
virtual bool sendEvent(SignallingEvent* event);
|
|
|
|
/**
|
|
* Get an event from this call
|
|
* This method is thread safe
|
|
* @param when The current time
|
|
* @return SignallingEvent pointer or 0 if no events
|
|
*/
|
|
virtual SignallingEvent* getEvent(const Time& when);
|
|
|
|
/**
|
|
* Data link (interface) state notification
|
|
* This method is thread safe
|
|
* @param up The data link state
|
|
*/
|
|
void dataLinkState(bool up);
|
|
|
|
/**
|
|
* Get a pointer to a data member or this call
|
|
* @param name Object name
|
|
* @return The requested pointer or 0 if not exists
|
|
*/
|
|
virtual void* getObject(const String& name) const;
|
|
|
|
protected:
|
|
/**
|
|
* Constructor
|
|
* @param controller The call controller
|
|
* @param outgoing The call direction
|
|
* @param callRef The call reference
|
|
* @param callRefLen The call reference length in bytes
|
|
* @param tei The Terminal Equipment Identifier used in this call
|
|
*/
|
|
ISDNQ931Call(ISDNQ931* controller, bool outgoing, u_int32_t callRef,
|
|
u_int8_t callRefLen, u_int8_t tei = 0);
|
|
|
|
/**
|
|
* Send RELEASE COMPLETE if not in Null state.
|
|
* Clear all call data.
|
|
* Remove from controller's queue. Decrease the object's refence count
|
|
* @param reason Optional release reason. If missing, the last reason is used
|
|
* @param diag Optional hexified string for the cause diagnostic
|
|
* @return Pointer to an SignallingEvent of type Release, with no message
|
|
*/
|
|
SignallingEvent* releaseComplete(const char* reason = 0, const char* diag = 0);
|
|
|
|
/**
|
|
* Get an event from the circuit reserved for this call
|
|
* @param when The current time
|
|
* @return SignallingEvent pointer or 0 if no events
|
|
*/
|
|
SignallingEvent* getCircuitEvent(const Time& when);
|
|
|
|
private:
|
|
// Reserve and connect a circuit. Change the reserved one if it must to
|
|
bool reserveCircuit();
|
|
// Process call when terminate flag is set. Check timeout
|
|
// @param msg Optional message extracted from queue
|
|
SignallingEvent* processTerminate(ISDNQ931Message* msg = 0);
|
|
// Check timer(s)
|
|
SignallingEvent* checkTimeout(u_int64_t time);
|
|
// Check received messages for valid state
|
|
// True to send status if not accepted
|
|
bool checkMsgRecv(ISDNQ931Message* msg, bool status);
|
|
// Process received messages
|
|
// @param msg Valid ISDNQ931Message pointer
|
|
SignallingEvent* processMsgAlerting(ISDNQ931Message* msg);
|
|
SignallingEvent* processMsgCallProceeding(ISDNQ931Message* msg);
|
|
SignallingEvent* processMsgConnect(ISDNQ931Message* msg);
|
|
SignallingEvent* processMsgConnectAck(ISDNQ931Message* msg);
|
|
SignallingEvent* processMsgDisconnect(ISDNQ931Message* msg);
|
|
SignallingEvent* processMsgInfo(ISDNQ931Message* msg);
|
|
SignallingEvent* processMsgNotify(ISDNQ931Message* msg);
|
|
SignallingEvent* processMsgProgress(ISDNQ931Message* msg);
|
|
SignallingEvent* processMsgRelease(ISDNQ931Message* msg);
|
|
SignallingEvent* processMsgSetup(ISDNQ931Message* msg);
|
|
SignallingEvent* processMsgSetupAck(ISDNQ931Message* msg);
|
|
SignallingEvent* processMsgStatus(ISDNQ931Message* msg);
|
|
SignallingEvent* processMsgStatusEnquiry(ISDNQ931Message* msg);
|
|
// Send message
|
|
// @param msg Pointer to SignallingMessage with parameters
|
|
bool sendAlerting(SignallingMessage* sigMsg);
|
|
bool sendCallProceeding(SignallingMessage* sigMsg);
|
|
bool sendConnect(SignallingMessage* sigMsg);
|
|
bool sendConnectAck(SignallingMessage* sigMsg);
|
|
bool sendDisconnect(SignallingMessage* sigMsg);
|
|
bool sendInfo(SignallingMessage* sigMsg);
|
|
bool sendProgress(SignallingMessage* sigMsg);
|
|
bool sendRelease(const char* reason = 0, SignallingMessage* sigMsg = 0);
|
|
bool sendReleaseComplete(const char* reason = 0, const char* diag = 0, u_int8_t tei = 0);
|
|
bool sendSetup(SignallingMessage* sigMsg);
|
|
bool sendSuspendRej(const char* reason = 0, SignallingMessage* sigMsg = 0);
|
|
bool sendSetupAck();
|
|
// Errors on processing received messages
|
|
// Missing mandatory IE
|
|
// @param release True to send release complete and generate a release event
|
|
SignallingEvent* errorNoIE(ISDNQ931Message* msg, ISDNQ931IE::Type type, bool release);
|
|
SignallingEvent* errorWrongIE(ISDNQ931Message* msg, ISDNQ931IE::Type type, bool release);
|
|
// Change call state
|
|
void changeState(State newState);
|
|
// Remove the call from controller's list
|
|
void removeFromController();
|
|
// Get the Q931 call controller
|
|
inline ISDNQ931* q931();
|
|
|
|
// Call data
|
|
u_int32_t m_callRef; // Call reference
|
|
u_int32_t m_callRefLen; // Call reference length
|
|
u_int8_t m_tei; // TEI used for the call
|
|
SignallingCircuit* m_circuit; // Circuit reserved for this call
|
|
bool m_overlap; // Call is using overlapped sending
|
|
bool m_circuitChange; // True if circuit changed
|
|
bool m_channelIDSent; // Incoming calls: ChannelID IE already sent
|
|
bool m_rspBearerCaps; // Incoming calls: Send BearerCaps IE in the first response
|
|
bool m_net; // Flag indicating call is sent by a NT
|
|
ISDNQ931IEData m_data; // Data to process IEs
|
|
ObjList m_inMsg; // Incoming message queue
|
|
bool m_broadcast[127]; // TEIs that answered to PTMP SETUP
|
|
// Timers
|
|
SignallingTimer m_discTimer; // T305: sending DISCONNECT
|
|
SignallingTimer m_relTimer; // T308: sending RELEASE
|
|
SignallingTimer m_conTimer; // T313: sending CONNECT
|
|
SignallingTimer m_overlapSendTimer; // T302 for overlapped sending
|
|
SignallingTimer m_overlapRecvTimer; // T304
|
|
SignallingTimer m_retransSetupTimer; // T302 for setup retransmission (PTMP)
|
|
// Termination
|
|
bool m_terminate; // Terminate flag: send RELEASE
|
|
bool m_destroy; // Destroy flag: call releaseComplete()
|
|
bool m_destroyed; // Call destroyed flag
|
|
};
|
|
|
|
/**
|
|
* Q.931 ISDN call monitor
|
|
* @short A Q.931 ISDN call monitor
|
|
*/
|
|
class YSIG_API ISDNQ931CallMonitor : public ISDNQ931State, public SignallingCall
|
|
{
|
|
friend class ISDNQ931Monitor;
|
|
public:
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~ISDNQ931CallMonitor();
|
|
|
|
/**
|
|
* Check if the initiator is from the network side of the data link
|
|
* @return True if the initiator is from the network side of the data link, false if it is from the user side
|
|
*/
|
|
inline bool netInit() const
|
|
{ return m_netInit; }
|
|
|
|
/**
|
|
* Get an event from this call
|
|
* This method is thread safe
|
|
* @param when The current time
|
|
* @return SignallingEvent pointer or 0 if no events
|
|
*/
|
|
virtual SignallingEvent* getEvent(const Time& when);
|
|
|
|
/**
|
|
* Set termination flag
|
|
* This method is thread safe
|
|
* @param reason Terminate reason
|
|
*/
|
|
void setTerminate(const char* reason);
|
|
|
|
/**
|
|
* Get a pointer to a data member or this call
|
|
* @param name Object name
|
|
* @return The requested pointer or 0 if not exists
|
|
*/
|
|
virtual void* getObject(const String& name) const;
|
|
|
|
protected:
|
|
/**
|
|
* Constructor
|
|
* @param controller The call controller
|
|
* @param callRef The call reference
|
|
* @param netInit True if the initiator is from the network side of the link
|
|
*/
|
|
ISDNQ931CallMonitor(ISDNQ931Monitor* controller, u_int32_t callRef, bool netInit);
|
|
|
|
/**
|
|
* Clear all call data
|
|
* Remove from controller's queue. Decrease the object's refence count
|
|
* @param reason Optional release reason. If missing, the last reason is used
|
|
* @return Pointer to an SignallingEvent of type Release
|
|
*/
|
|
SignallingEvent* releaseComplete(const char* reason = 0);
|
|
|
|
private:
|
|
// Get an event from one of the reserved circuits
|
|
SignallingEvent* getCircuitEvent(const Time& when);
|
|
// Process received setup message
|
|
SignallingEvent* processMsgSetup(ISDNQ931Message* msg);
|
|
// Process received responses to setup message (Proceeding, Alerting, Connect)
|
|
SignallingEvent* processMsgResponse(ISDNQ931Message* msg);
|
|
// Process termination messages (Disconnect, Release, Release Complete)
|
|
SignallingEvent* processMsgTerminate(ISDNQ931Message* msg);
|
|
// Process INFORMATION messages to get tones
|
|
SignallingEvent* processMsgInfo(ISDNQ931Message* msg);
|
|
// Reserve/release the circuits
|
|
bool reserveCircuit();
|
|
void releaseCircuit();
|
|
// Connect the caller's or called's circuit
|
|
bool connectCircuit(bool caller);
|
|
// Change call state
|
|
void changeState(State newState);
|
|
// Remove the call from controller's list
|
|
void removeFromController();
|
|
// Get the Q931Monitor call controller
|
|
inline ISDNQ931Monitor* q931();
|
|
|
|
u_int32_t m_callRef; // Call reference
|
|
SignallingCircuit* m_callerCircuit; // Circuit reserved for caller
|
|
SignallingCircuit* m_calledCircuit; // Circuit reserved for called
|
|
SignallingCircuit* m_eventCircuit; // Last circuit that generated an event
|
|
bool m_netInit; // The call initiator is from the network side of the link
|
|
bool m_circuitChange; // True if circuit changed
|
|
ISDNQ931IEData m_data; // Data to process IEs
|
|
bool m_terminate; // Terminate flag
|
|
String m_terminator; // The name of the entity that terminated the call
|
|
ObjList m_inMsg; // Incoming messages queue
|
|
};
|
|
|
|
/**
|
|
* This class holds Q.931 parser settings used to encode/decode Q.931 messages
|
|
* @short Q.931 message parser data
|
|
*/
|
|
class YSIG_API ISDNQ931ParserData
|
|
{
|
|
public:
|
|
/**
|
|
* Constructor
|
|
* @param params Parser settings
|
|
* @param dbg The debug enabler used for output
|
|
*/
|
|
ISDNQ931ParserData(const NamedList& params, DebugEnabler* dbg = 0);
|
|
|
|
/**
|
|
* Check the state of a flag
|
|
* @param mask The flag to check
|
|
* @return True if the given flag is set
|
|
*/
|
|
inline bool flag(int mask)
|
|
{ return (0 != (m_flags & mask)); }
|
|
|
|
DebugEnabler* m_dbg; // The debug enabler used for output
|
|
u_int32_t m_maxMsgLen; // Maximum length of outgoing messages (or message segments)
|
|
int m_flags; // The current behaviour flags
|
|
int m_flagsOrig; // The original behaviour flags
|
|
u_int8_t m_maxDisplay; // Max Display IE size
|
|
bool m_allowSegment; // True if message segmentation is allowed
|
|
u_int8_t m_maxSegments; // Maximum allowed segments for outgoing messages
|
|
bool m_extendedDebug; // True to fill message/IE buffer
|
|
};
|
|
|
|
/**
|
|
* Q.931 ISDN Layer 3 implementation on top of a Layer 2
|
|
* @short ISDN Q.931 implementation on top of Q.921
|
|
*/
|
|
class YSIG_API ISDNQ931 : public SignallingCallControl, public SignallingDumpable, public ISDNLayer3
|
|
{
|
|
YCLASS(ISDNQ931,ISDNLayer3)
|
|
friend class ISDNQ931Call;
|
|
public:
|
|
/**
|
|
* Enumeration flags defining the behaviour of the ISDN call controller and
|
|
* any active calls managed by it
|
|
*/
|
|
enum BehaviourFlags {
|
|
// Append the progress indicator 'non-isdn-source' if present when
|
|
// sending SETUP. If this flag is not set, the indicator will be
|
|
// removed from the message
|
|
SendNonIsdnSource = 0x00000001,
|
|
// Ignore (don't send) the progress indicator 'non-isdn-destination'
|
|
// if present when sending SETUP ACKNOWLEDGE or CONNECT
|
|
IgnoreNonIsdnDest = 0x00000002,
|
|
// Always set presentation='allowed' and screening='network-provided'
|
|
// for Calling Party Number IE
|
|
ForcePresNetProv = 0x00000004,
|
|
// Translate '3.1khz-audio' transfer capability code 0x10 to/from 0x08
|
|
Translate31kAudio = 0x00000008,
|
|
// Send only tranfer mode and rate when sending the Bearer Capability IE
|
|
// with transfer capability 'udi' or 'rdi' (unrestricted/restricted
|
|
// digital information)
|
|
URDITransferCapsOnly = 0x00000010,
|
|
// Don't send Layer 1 capabilities (data format) with the
|
|
// Bearer Capability IE when in circuit switch mode
|
|
NoLayer1Caps = 0x00000020,
|
|
// Don't parse incoming IEs found after a temporary (non-locking) shift
|
|
IgnoreNonLockedIE = 0x00000040,
|
|
// Don't send the Display IE
|
|
// This flag is internally set for EuroIsdnE1 type when the call
|
|
// controller is the CPE side of the link
|
|
NoDisplayIE = 0x00000080,
|
|
// Don't append a charset byte 0xb1 before Display data
|
|
NoDisplayCharset = 0x00000100,
|
|
// Send a Sending Complete IE even if no overlap dialing
|
|
ForceSendComplete = 0x00000200,
|
|
// Don't change call state to Active instead of ConnectRequest after
|
|
// sending CONNECT. This flag is internally set when the call
|
|
// controller is the CPE side of the data link
|
|
NoActiveOnConnect = 0x00000400,
|
|
// Check the validity of the notification indicator when sending a NOTIFY message
|
|
CheckNotifyInd = 0x00000800,
|
|
};
|
|
|
|
/**
|
|
* Call controller switch type. Each value is a mask of behaviour flags
|
|
*/
|
|
enum SwitchType {
|
|
Unknown = 0,
|
|
// Standard Euro ISDN (CTR4, ETSI 300-102)
|
|
EuroIsdnE1 = ForceSendComplete|CheckNotifyInd|NoDisplayCharset|URDITransferCapsOnly,
|
|
// T1 Euro ISDN variant (ETSI 300-102)
|
|
EuroIsdnT1 = ForceSendComplete|CheckNotifyInd,
|
|
// National ISDN
|
|
NationalIsdn = SendNonIsdnSource,
|
|
// DMS 100
|
|
Dms100 = ForcePresNetProv|IgnoreNonIsdnDest,
|
|
// Lucent 5E
|
|
Lucent5e = IgnoreNonLockedIE,
|
|
// AT&T 4ESS
|
|
Att4ess = ForcePresNetProv|IgnoreNonLockedIE|Translate31kAudio|NoLayer1Caps,
|
|
// QSIG Switch
|
|
QSIG = NoActiveOnConnect|NoDisplayIE|NoDisplayCharset
|
|
};
|
|
|
|
/**
|
|
* Constructor
|
|
* Initialize this object and the component
|
|
* @param params Layer's parameters and parser settings
|
|
* @param name Name of this component
|
|
*/
|
|
ISDNQ931(const NamedList& params, const char* name = 0);
|
|
|
|
/**
|
|
* Destructor
|
|
* Destroy all calls
|
|
*/
|
|
virtual ~ISDNQ931();
|
|
|
|
/**
|
|
* Configure and initialize Q.931 and its layer 2
|
|
* @param config Optional configuration parameters override
|
|
* @return True if Q.931 and the layer 2 were initialized properly
|
|
*/
|
|
virtual bool initialize(const NamedList* config);
|
|
|
|
/**
|
|
* Get the layer 2 attached to this object
|
|
* @return Pointer to the layer 2 attached to this object or 0 if none
|
|
*/
|
|
inline const ISDNLayer2* layer2() const
|
|
{ return m_q921; }
|
|
|
|
/**
|
|
* Check if this call controller supports primary or basic rate transfer
|
|
* @return True for primary rate. False for basic rate
|
|
*/
|
|
inline bool primaryRate() const
|
|
{ return m_primaryRate; }
|
|
|
|
/**
|
|
* Chech if this call controller is at the NET or CPE side of the link
|
|
* @return True if we are NET, false if we are CPE
|
|
*/
|
|
inline bool network() const
|
|
{ return m_q921 ? m_q921->network() : m_networkHint; }
|
|
|
|
/**
|
|
* Check if this call controller supports circuit switch or packet mode transfer
|
|
* @return True for circuit switch. False for packet mode
|
|
*/
|
|
inline bool transferModeCircuit() const
|
|
{ return m_transferModeCircuit; }
|
|
|
|
/**
|
|
* Get the parser settings of this call control
|
|
* @return The parser settings
|
|
*/
|
|
inline ISDNQ931ParserData& parserData()
|
|
{ return m_parserData; }
|
|
|
|
/**
|
|
* Get the default numbering plan for outgoing calls
|
|
* @return The default numbering plan for outgoing calls
|
|
*/
|
|
inline const String& numPlan() const
|
|
{ return m_numPlan; }
|
|
|
|
/**
|
|
* Get the default number type for outgoing calls
|
|
* @return The default number type for outgoing calls
|
|
*/
|
|
inline const String& numType() const
|
|
{ return m_numType; }
|
|
|
|
/**
|
|
* Get the default number presentation for outgoing calls
|
|
* @return The default number presentation for outgoing calls
|
|
*/
|
|
inline const String& numPresentation() const
|
|
{ return m_numPresentation; }
|
|
|
|
/**
|
|
* Get the default number screening for outgoing calls
|
|
* @return The default number screening for outgoing calls
|
|
*/
|
|
inline const String& numScreening() const
|
|
{ return m_numScreening; }
|
|
|
|
/**
|
|
* Get the default data format for outgoing calls
|
|
* @return The default data format for outgoing calls
|
|
*/
|
|
inline const String& format() const
|
|
{ return m_format; }
|
|
|
|
/**
|
|
* Send a message
|
|
* @param msg The message to be sent
|
|
* @param tei TEI value to use at Layer 2
|
|
* @param reason Optional string to write the failure reason
|
|
* @return False if the message is invalid, Layer 2 is missing or refused the data
|
|
*/
|
|
bool sendMessage(ISDNQ931Message* msg, u_int8_t tei, String* reason = 0);
|
|
|
|
/**
|
|
* Notification of Layer 2 up state
|
|
* @param tei TEI received by the Layer 2
|
|
* @param confirm True if this is a confirmation of a previous request.
|
|
* False if it is an indication of state change on remote request
|
|
* @param timeout True if the reason is a timeout.
|
|
* @param layer2 Pointer to the notifier
|
|
*/
|
|
virtual void multipleFrameEstablished(u_int8_t tei, bool confirm, bool timeout, ISDNLayer2* layer2);
|
|
|
|
/**
|
|
* Notification of Layer 2 down state
|
|
* @param tei TEI received by the Layer 2
|
|
* @param confirm True if this is a confirmation of a previous request.
|
|
* False if it is an indication of state change on remote request
|
|
* @param timeout True if the reason is a timeout.
|
|
* @param layer2 Pointer to the notifier
|
|
*/
|
|
virtual void multipleFrameReleased(u_int8_t tei, bool confirm, bool timeout, ISDNLayer2* layer2);
|
|
|
|
/**
|
|
* Receive data from Layer 2
|
|
* @param data Received data
|
|
* @param tei TEI received by the Layer 2
|
|
* @param layer2 Pointer to the sender Layer 2
|
|
*/
|
|
virtual void receiveData(const DataBlock& data, u_int8_t tei, ISDNLayer2* layer2);
|
|
|
|
/**
|
|
* Attach an ISDN Q.921 transport
|
|
* This method is thread safe
|
|
* @param q921 Pointer to the Q.921 transport to attach
|
|
* @return Pointer to the detached Layer 2 or NULL
|
|
*/
|
|
virtual ISDNLayer2* attach(ISDNLayer2* q921);
|
|
|
|
/**
|
|
* Create an outgoing call. Send a NewCall event with the given msg parameter
|
|
* @param msg Call parameters
|
|
* @param reason Failure reason if any
|
|
* @return Referenced SignallingCall pointer on success or 0 on failure
|
|
*/
|
|
SignallingCall* call(SignallingMessage* msg, String& reason);
|
|
|
|
/**
|
|
* Restart one or more the circuits
|
|
* @param circuits Comma separated list of circuits to be restarted
|
|
* @return True if the procedure was succesfully started or enqueued
|
|
*/
|
|
bool restart(const char* circuits);
|
|
|
|
/**
|
|
* Send a STATUS message for a given call
|
|
* @param call The call requesting the operation
|
|
* @param tei The TEI to send with the STATUS message
|
|
* @param cause Value for Cause IE
|
|
* @param display Optional value for Display IE
|
|
* @param diagnostic Optional value for cause diagnostic value
|
|
* @return The result of the operation (true if succesfully sent)
|
|
*/
|
|
inline bool sendStatus(ISDNQ931Call* call, const char* cause, u_int8_t tei = 0,
|
|
const char* display = 0, const char* diagnostic = 0)
|
|
{
|
|
return call && sendStatus(cause,call->callRefLen(),call->callRef(),tei,
|
|
call->outgoing(),call->state(),display,diagnostic);
|
|
}
|
|
|
|
/**
|
|
* Send a RELEASE or RELEASE COMPLETE message for a given call
|
|
* @param call The call requesting the operation
|
|
* @param release True to send RELEASE, false to send RELEASE COMPLETE
|
|
* @param cause Value for Cause IE
|
|
* @param tei TEI to which the release is sent to
|
|
* @param diag Optional hexified string for cause dignostic
|
|
* @param display Optional value for Display IE
|
|
* @param signal Optional value for Signal IE
|
|
* @return The result of the operation (true if succesfully sent)
|
|
*/
|
|
inline bool sendRelease(ISDNQ931Call* call, bool release, const char* cause, u_int8_t tei = 0,
|
|
const char* diag = 0, const char* display = 0, const char* signal = 0)
|
|
{
|
|
return call && sendRelease(release,call->callRefLen(),call->callRef(),tei,
|
|
call->outgoing(),cause,diag,display,signal);
|
|
}
|
|
|
|
/**
|
|
* Set terminate to all calls
|
|
* This method is thread safe
|
|
* @param reason Cleanup reason
|
|
*/
|
|
virtual void cleanup(const char* reason = "offline");
|
|
|
|
/**
|
|
* Set the timeout interval for a given timer if implemented
|
|
* If the timer is not implemented the interval is set to 0
|
|
* @param timer The destination timer
|
|
* @param id The timer number as defined in Q.931
|
|
*/
|
|
void setInterval(SignallingTimer& timer, int id);
|
|
|
|
/**
|
|
* Manage timeout for the call setup message
|
|
*/
|
|
void manageTimeout();
|
|
|
|
/**
|
|
* Set debug data of this call controller
|
|
* @param printMsg Enable/disable message printing on output
|
|
* @param extendedDebug Enable/disable hex data dump if print messages is enabled
|
|
*/
|
|
inline void setDebug(bool printMsg, bool extendedDebug)
|
|
{ m_parserData.m_extendedDebug = m_extendedDebug =
|
|
((m_printMsg = printMsg) && extendedDebug); }
|
|
|
|
/**
|
|
* The list of behaviour flag names
|
|
*/
|
|
static TokenDict s_flags[];
|
|
|
|
/**
|
|
* The list of switch type names
|
|
*/
|
|
static TokenDict s_swType[];
|
|
|
|
protected:
|
|
/**
|
|
* Detach links. Disposes memory
|
|
*/
|
|
virtual void destroyed()
|
|
{
|
|
TelEngine::destruct(attach(0));
|
|
TelEngine::destruct(SignallingCallControl::attach(0));
|
|
ISDNLayer3::destroyed();
|
|
}
|
|
|
|
/**
|
|
* Method called periodically to check timeouts
|
|
* This method is thread safe
|
|
* @param when Time to use as computing base for events and timeouts
|
|
*/
|
|
virtual void timerTick(const Time& when);
|
|
|
|
/**
|
|
* Find a call given its call reference and direction
|
|
* @param callRef The call reference to find
|
|
* @param outgoing True to find an outgoing call, false to find an incoming one
|
|
* @param tei TEI of the layer associated to the call to find
|
|
* @return A referenced pointer to a call or 0
|
|
*/
|
|
ISDNQ931Call* findCall(u_int32_t callRef, bool outgoing, u_int8_t tei = 0);
|
|
|
|
/**
|
|
* Find a call given a circuit number
|
|
* @param circuit The circuit number to find
|
|
* @return A referenced pointer to a call or 0
|
|
*/
|
|
ISDNQ931Call* findCall(unsigned int circuit);
|
|
|
|
/**
|
|
* Terminate calls. If list is 0 terminate all calls
|
|
* @param list Optional list of circuits (strings) to be released
|
|
* @param reason The reason to be passed to each terminated call
|
|
*/
|
|
void terminateCalls(ObjList* list, const char* reason);
|
|
|
|
/**
|
|
* Check if this call control can accept new calls
|
|
* @param outgoing Call direction (true for outgoing)
|
|
* @param reason String to be filled with the reason if not accepted
|
|
* @return True if the call request is accepted
|
|
*/
|
|
bool acceptNewCall(bool outgoing, String& reason);
|
|
|
|
/**
|
|
* Process received data. Process received message segments if any
|
|
* @param data The received data
|
|
* @return ISDNQ931Message pointer or 0
|
|
*/
|
|
ISDNQ931Message* getMsg(const DataBlock& data);
|
|
|
|
/**
|
|
* End waiting for message segments
|
|
* If reason is 0 parse already received data for the segmented message
|
|
* This method is thread safe
|
|
* @param reason Debug info reason. If non 0 drop the received segment(s)
|
|
* @return ISDNQ931Message pointer or 0
|
|
*/
|
|
ISDNQ931Message* endReceiveSegment(const char* reason = 0);
|
|
|
|
/**
|
|
* Process messages with global call reference or should have one
|
|
* @param msg The received message
|
|
* @param tei The TEI received with the message
|
|
*/
|
|
void processGlobalMsg(ISDNQ931Message* msg, u_int8_t tei = 0);
|
|
|
|
/**
|
|
* Process a restart request
|
|
* @param msg The received message
|
|
* @param tei The TEI received with the message
|
|
*/
|
|
void processMsgRestart(ISDNQ931Message* msg, u_int8_t tei = 0);
|
|
|
|
/**
|
|
* Process messages with invalid call reference
|
|
* @param msg The received message
|
|
* @param tei The TEI received with the message
|
|
*/
|
|
void processInvalidMsg(ISDNQ931Message* msg, u_int8_t tei = 0);
|
|
|
|
/**
|
|
* Try to reserve a circuit for restarting if none. Send a restart request on it's behalf
|
|
* Start counting the restart interval if no circuit reserved
|
|
* This method is thread safe
|
|
* @param time The time of the transmission
|
|
* @param retrans Retransmission flag (true if a previous request timed out)
|
|
*/
|
|
void sendRestart(u_int64_t time = Time::msecNow(), bool retrans = false);
|
|
|
|
/**
|
|
* End restart procedure on timeout or restart acknoledge
|
|
* This method is thread safe
|
|
* @param restart True to try to send restart for the next circuit
|
|
* @param time The time of the transmission
|
|
* @param timeout True if a restart request timed out
|
|
*/
|
|
void endRestart(bool restart, u_int64_t time, bool timeout = false);
|
|
|
|
/**
|
|
* Send a STATUS message
|
|
* @param cause Value for Cause IE
|
|
* @param callRefLen The call reference length parameter.
|
|
* @param callRef The call reference
|
|
* @param tei The TEI to send with the STATUS message
|
|
* @param initiator True if this is from the call initiator
|
|
* @param state The state for CallState IE
|
|
* @param display Optional value for Display IE
|
|
* @param diagnostic Optional value for cause diagnostic value
|
|
* @return The result of the operation (true if succesfully sent)
|
|
*/
|
|
bool sendStatus(const char* cause, u_int8_t callRefLen, u_int32_t callRef = 0,
|
|
u_int8_t tei = 0, bool initiator = false, ISDNQ931Call::State state = ISDNQ931Call::Null,
|
|
const char* display = 0, const char* diagnostic = 0);
|
|
|
|
/**
|
|
* Send a RELEASE or RELEASE COMPLETE message
|
|
* @param release True to send RELEASE, false to send RELEASE COMPLETE
|
|
* @param callRefLen The call reference length parameter
|
|
* @param callRef The call reference
|
|
* @param tei The TEI of the Layer 2 associated with the call
|
|
* @param initiator The call initiator flag
|
|
* @param cause Value for Cause IE
|
|
* @param diag Optional hexified string for cause dignostic
|
|
* @param display Optional value for Display IE
|
|
* @param signal Optional value for Signal IE
|
|
* @return The result of the operation (true if succesfully sent)
|
|
*/
|
|
bool sendRelease(bool release, u_int8_t callRefLen, u_int32_t callRef, u_int8_t tei,
|
|
bool initiator, const char* cause = 0, const char* diag = 0,
|
|
const char* display = 0, const char* signal = 0);
|
|
|
|
private:
|
|
virtual bool control(NamedList& params)
|
|
{ return SignallingDumpable::control(params,this); }
|
|
bool q921Up() const; // Check if layer 2 may be up
|
|
ISDNLayer2* m_q921; // The attached layer 2
|
|
bool m_q921Up; // Layer 2 state
|
|
// Protocol data
|
|
bool m_networkHint; // NET / CPE hint, layer 2 is authoritative
|
|
bool m_primaryRate; // Primary/base rate support
|
|
bool m_transferModeCircuit; // Circuit switch/packet mode transfer
|
|
u_int32_t m_callRef; // Current available call reference for outgoing calls
|
|
u_int8_t m_callRefLen; // Call reference length
|
|
u_int32_t m_callRefMask; // Call reference mask
|
|
ISDNQ931ParserData m_parserData; // Parser settings
|
|
ISDNQ931IEData m_data; // Process IEs
|
|
// Timers & counters
|
|
SignallingTimer m_l2DownTimer; // T309: Layer 2 is down timeout
|
|
SignallingTimer m_recvSgmTimer; // T314: Receive segment timeout
|
|
SignallingTimer m_syncCicTimer; // T316: Restart individual circuit timeout
|
|
SignallingCounter m_syncCicCounter; // RESTART retransmission counter
|
|
SignallingTimer m_callDiscTimer; // Q931 call value (see ISDQ931Call)
|
|
SignallingTimer m_callRelTimer; // Q931 call value (see ISDQ931Call)
|
|
SignallingTimer m_callConTimer; // Q931 call value (see ISDQ931Call)
|
|
// Default values
|
|
String m_numPlan; // Numbering plan
|
|
String m_numType; // Number type
|
|
String m_numPresentation; // Number presentation
|
|
String m_numScreening; // Number screening
|
|
String m_format; // Data format
|
|
String m_cpeNumber; // The number of the BRI CPE
|
|
// Restart data
|
|
SignallingCircuit* m_restartCic; // Currently restarting circuit
|
|
unsigned int m_lastRestart; // Last restarted circuit's code
|
|
SignallingTimer m_syncGroupTimer; // Restarting circuit group interval
|
|
// Message segmentation data
|
|
DataBlock m_segmentData; // Message segments buffer
|
|
ISDNQ931Message* m_segmented; // Segmented message
|
|
u_int8_t m_remaining; // Remaining segments
|
|
// Debug
|
|
bool m_printMsg; // True to print messages to output
|
|
bool m_extendedDebug; // Extended debug flag
|
|
// Flags used to print error messages
|
|
bool m_flagQ921Down; // Layer 2 is down period timed out
|
|
bool m_flagQ921Invalid; // Refusing to send message when Layer 2 is missing or down
|
|
};
|
|
|
|
/**
|
|
* Q.931 ISDN Layer 3 implementation on top of a Layer 2. Manage Q.931 monitors
|
|
* @short ISDN Q.931 implementation on top of Q.921 of call controller monitor
|
|
*/
|
|
class YSIG_API ISDNQ931Monitor : public SignallingCallControl, public ISDNLayer3
|
|
{
|
|
YCLASS(ISDNQ931Monitor,ISDNLayer3)
|
|
friend class ISDNQ931CallMonitor;
|
|
public:
|
|
/**
|
|
* Constructor
|
|
* Initialize this object and the component
|
|
* @param params Layer's parameters and parser settings
|
|
* @param name Name of this component
|
|
*/
|
|
ISDNQ931Monitor(const NamedList& params, const char* name = 0);
|
|
|
|
/**
|
|
* Destructor
|
|
* Destroy all calls
|
|
*/
|
|
virtual ~ISDNQ931Monitor();
|
|
|
|
/**
|
|
* Configure and initialize the Q.931 monitor and its interfaces
|
|
* @param config Optional configuration parameters override
|
|
* @return True if Q.931 monitor and both interfaces were initialized properly
|
|
*/
|
|
virtual bool initialize(const NamedList* config);
|
|
|
|
/**
|
|
* Notification from layer 2 of data link set/release command or response
|
|
* @param tei The TEI of the notification
|
|
* @param cmd True if received a command, false if received a response
|
|
* @param value The value of the notification
|
|
* If 'cmd' is true (command), the value is true if a request to establish data link was received
|
|
* or false if received a request to release data link
|
|
* If 'cmd' is false (response), the value is the response
|
|
* @param layer2 Pointer to the notifier
|
|
*/
|
|
virtual void dataLinkState(u_int8_t tei, bool cmd, bool value, ISDNLayer2* layer2);
|
|
|
|
/**
|
|
* Notification from layer 2 of data link idle timeout
|
|
* @param layer2 Pointer to the notifier
|
|
*/
|
|
virtual void idleTimeout(ISDNLayer2* layer2);
|
|
|
|
/**
|
|
* Implements Q.921 DL-DATA and DL-UNIT DATA indication primitives
|
|
* @param data Received data
|
|
* @param tei The TEI of the Layer 2
|
|
* @param layer2 Pointer to the sender
|
|
*/
|
|
virtual void receiveData(const DataBlock& data, u_int8_t tei, ISDNLayer2* layer2);
|
|
|
|
/**
|
|
* Attach ISDN Q.921 pasive transport that monitors one side of the link
|
|
* This method is thread safe
|
|
* @param q921 Pointer to the monitor to attach
|
|
* @param net True if this is the network side of the data link, false for user (CPE) side
|
|
* @return Pointer to detached monitor or NULL
|
|
*/
|
|
virtual ISDNQ921Passive* attach(ISDNQ921Passive* q921, bool net);
|
|
|
|
/**
|
|
* Attach a circuit group to this call controller
|
|
* This method is thread safe
|
|
* @param circuits Pointer to the SignallingCircuitGroup to attach
|
|
* @param net True if this group belongs to the network side of the data link, false for user (CPE) side
|
|
* @return Pointer to the old group that was detached, NULL if none or no change
|
|
*/
|
|
virtual SignallingCircuitGroup* attach(SignallingCircuitGroup* circuits, bool net);
|
|
|
|
/**
|
|
* Get a pointer to the NET or CPE circuit group
|
|
* @param net True to get the network side circuits, false for user (CPE) side
|
|
* @return Pointer to the circuit group requested, NULL if none attached
|
|
*/
|
|
inline ISDNQ921Passive* circuits(bool net) const
|
|
{ return net ? m_q921Net : m_q921Cpe; }
|
|
|
|
/**
|
|
* Set debug data of this call controller
|
|
* @param printMsg Enable/disable message printing on output
|
|
* @param extendedDebug Enable/disable hex data dump if print messages is enabled
|
|
*/
|
|
inline void setDebug(bool printMsg, bool extendedDebug)
|
|
{ m_parserData.m_extendedDebug = m_extendedDebug =
|
|
((m_printMsg = printMsg) && extendedDebug); }
|
|
|
|
/**
|
|
* Terminate all monitors
|
|
* This method is thread safe
|
|
* @param reason Cleanup reason
|
|
*/
|
|
virtual void cleanup(const char* reason = "offline")
|
|
{ terminateMonitor(0,reason); }
|
|
|
|
/**
|
|
* Terminate all monitors or only one
|
|
* This method is thread safe
|
|
* @param mon The monitor to terminate, 0 to terminate all
|
|
* @param reason The termination reason
|
|
*/
|
|
void terminateMonitor(ISDNQ931CallMonitor* mon, const char* reason);
|
|
|
|
protected:
|
|
/**
|
|
* Detach links. Disposes memory
|
|
*/
|
|
virtual void destroyed()
|
|
{
|
|
TelEngine::destruct(SignallingCallControl::attach(0));
|
|
TelEngine::destruct(attach((ISDNQ921Passive*)0,true));
|
|
TelEngine::destruct(attach((ISDNQ921Passive*)0,false));
|
|
attach((SignallingCircuitGroup*)0,true);
|
|
attach((SignallingCircuitGroup*)0,false);
|
|
ISDNLayer3::destroyed();
|
|
}
|
|
|
|
/**
|
|
* Method called periodically to check timeouts
|
|
* This method is thread safe
|
|
* @param when Time to use as computing base for events and timeouts
|
|
*/
|
|
virtual void timerTick(const Time& when);
|
|
|
|
/**
|
|
* Reserve the same circuit code from both circuit groups
|
|
* This is an atomic operation: if one circuit fails to be reserved, both of them will fail
|
|
* Release both circuits on failure
|
|
* This method is thread safe
|
|
* @param code The circuit code to reserve
|
|
* @param netInit True if the caller is from the network side of the link, false if it's from CPE side
|
|
* @param caller The destination caller circuit
|
|
* @param called The destination called circuit
|
|
* @return True on success
|
|
*/
|
|
bool reserveCircuit(unsigned int code, bool netInit,
|
|
SignallingCircuit** caller, SignallingCircuit** called);
|
|
|
|
/**
|
|
* Release a circuit
|
|
* This method is thread safe
|
|
* @param circuit The circuit to release
|
|
* @return True on success
|
|
*/
|
|
bool releaseCircuit(SignallingCircuit* circuit);
|
|
|
|
/**
|
|
* Process a restart or restart acknoledge message
|
|
* Terminate the monitor having the circuit given in restart message
|
|
* @param msg The received message
|
|
*/
|
|
void processMsgRestart(ISDNQ931Message* msg);
|
|
|
|
private:
|
|
// Find a call monitor by call reference or reserved circuit
|
|
// @return Referenced call monitor pointer or 0 if not found
|
|
ISDNQ931CallMonitor* findMonitor(unsigned int value, bool byCallRef);
|
|
// Drop some messages. Return true if the message should be dropped
|
|
bool dropMessage(const ISDNQ931Message* msg);
|
|
|
|
ISDNQ921Passive* m_q921Net; // Net side of the link
|
|
ISDNQ921Passive* m_q921Cpe; // CPE side of the link
|
|
SignallingCircuitGroup* m_cicNet; // Circuit group for the net side of the link
|
|
SignallingCircuitGroup* m_cicCpe; // Circuit group for the cpe side of the link
|
|
ISDNQ931ParserData m_parserData; // Parser settings
|
|
ISDNQ931IEData m_data; // Process IEs
|
|
// Debug
|
|
bool m_printMsg; // True to print messages to output
|
|
bool m_extendedDebug; // Extended debug flag
|
|
};
|
|
|
|
}
|
|
|
|
#endif /* __YATESIG_H */
|
|
|
|
/* vi: set ts=8 sw=4 sts=4 noet: */
|