Added SNMP support.

git-svn-id: http://voip.null.ro/svn/yate@3776 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
oana 2010-11-03 16:27:30 +00:00
parent 1d9e0f3256
commit 55813dcbe3
42 changed files with 17644 additions and 41 deletions

View File

@ -0,0 +1,154 @@
; configure monitor module
[general]
; restart_alarm=
; after how many Yate restarts should the monitor send an alarm.
; default is 1
;restart_alarm=1
; time (in seconds) for specifying for how long cached data should be kept or with which the cache time is increased on each access
;cache=1
[database]
; enable or disable database monitoring. Default is false
;monitor=false
;[yate]
; this section is an example on how to configure a database account to be monitored
; name of the section is the database account
; type=
; specify that this section is for database monitoring
;type=database
;interval in seconds at which statistic data should be sent. Defaults to 3600 (1 hour)
;notiftime=3600
; alarm threshold for maximum number of queries. Defaults to 1000
;maxqueries=1000
; alarm threshold for maximum number of failed queries. Defaults to 500
;maxfailed=500
; alarm threshold for maximum number of queries returned with an error status. Defaults to 500
;maxerrors=500
; alarm threshold for time took to execute a query. In miliseconds, defaults to 10 seconds.
;maxtimeperquery=10000
[call_qos]
; this is the configuration section for call monitoring
; to disable call monitoring comment this entire section or set monitor to false. Defaults to false.
;monitor=false
; specify the call.cdr parameter based on which route monitoring should be done. Defaults to address.
;route=address
; time_interval=
; Time interval in seconds at which the monitored values should be sent as notifications.
; Default value is 3600 (1 hour)
;time_interval=3600
;[192.168.168.185]
; this section is an example on how to configure a routing direction to be monitor for ASR/NER values and call statistics
; name of this section is the routing direction name. It should match the value of the route param from the call.cdr message
; specify that this section is for call QOS monitoring on a given route
;type=call_qos
; minASR=
; lower threshold at which the low ASR alarm is set for the current time interval. Value can be 0..100
; Default is 0 ( to mean that no low ASR alarm will be sent)
;minASR=0
; maxASR=
; upper threshold at which the high ASR alarm is set for the current time interval.
; Default is 101 ( to mean that no high ASR alarm will be sent)
;maxASR=101
; minNER=
; threshold at which the low NER alarm should be set.
; Defaults to 0
;minNER=0
; minimum number of calls received before calculating ASR and NER
; Defaults to 1
;mincalls=1
[sip]
; monitoring SIP parameters
; list of gateways of which state to monitor
; It is a list of IP:port addresses separated by ';'
; If port is not present, the default SIP (5060) port will be added
;gateways=
; threshold for sending an alarm signalling to many failed SIP authentications. Default is 0 (no alarm)
;max_failed_auths=0
; threshold for sending an alarm signalling that too many SIP transactions have timed out. Default is 0 (no alarm)
;max_transaction_timeouts=0
;threshold for sending an alarm signalling that too many SIP BYE transactions have not been acknowledged. Default is 0 (no alarm)
;max_byes_timeouts=0
; reset interval for alarms in seconds. Default is 0 (meaning alarms are not reset)
;reset_time=0
[sig]
; enable monitoring for signalling components. Defaults to false.
;monitor=false
; monitor trunks. Overrides the monitor value. Defaults to the monitor value.
;trunk=
; monitor linkset. Overrides the monitor value. Defaults to the monitor value.
;linkset=
; monitor links. Overrides the monitor value. Defaults to the monitor value.
;link=
; monitor physical interfaces. Overrides the monitor value. Defaults to the monitor value.
;interface=
; monitor ISDN. Overrides the monitor value. Defaults to the monitor value.
;isdn=
[rtp]
; enable RTP monitoring? Defaults to false.
;monitor=false
; RTP destinations to be monitored. Should be a comma separated list.
; i.e. rtp_directions=192.168.168.185,127.0.0.1
;rtp_directions=
; interval in secconds at which collected data should be reset. Defaults to 3600 seconds.
;reset_interval=3600
[mgcp]
; send notification if a MGCP gateway goes offline/back online? Defaults to false.
;gw_monitor=false
; threshold for sending an alarm signalling that too many MGCP transactions have timed out. Default is 0 (no alarm)
;max_transaction_timeouts=0
; threshold for sending an alarm signalling that too many MGCP DLCX transactions have timed out. Default is 0 (no alarm)
;max_deletes_timeouts=0
; reset interval in seconds. Defaults to 0 (no reset)
;reset_time=0

View File

@ -0,0 +1,86 @@
[general]
; general SNMP configuration
; port on which the module listens for SNMP messages. Defaults to 161.
;port=161
;thread priority for SNMP message processing. Defaults to normal.
;thread=normal
[snmp_v2]
; SNMPv2 configuration
; read only access community string. Mandatory.
ro_community=
; read write access community string. Mandatory.
rw_community=
; read create access community string.
rc_community=
[snmp_v3]
; SNMPv3 configuration
; format for generating the snmpEngineID
; values are
; 1 = IPv4 address format,
; 2 = IPv6 address format,
; 3 = MAC address format,
; 4 = TEXT format,
; 5 = OCTETS format,
; 128 = ENTERPRISE specific format
; Defaults to 4 (TEXT)
;engine_format=4
; information for generating the snmpEngineID. Must correspond to the format set (i.e. if engine_format=1, engine_info must be a IPv4 address)
; NOTE! IPv6 address must not use the IPv6 short format. Mandatory.
; NOTE! OCTETS format must be a hexified string
engine_info=
[traps]
; SNMP traps configuration
;enable or disable all_notifications. Defaults to true.
;enable_traps=true
; list traps to disable. Must be separated by ','.
; An entire substree of traps can be disabled by ending the name of the trap with ".*"
; (e.g. disable the whole database status traps by adding database.*)
disable_traps=
; IP address to which the traps are sent. Defaults to localhost.
;remote_ip=localhost
; port for the remote IP. Defaults to 162.
;remote_port=162
;SNMP protocol version to use for sending traps (values are SNMPv2c or SNMPv3). Defaults to SNMPv2c.
;proto_version=SNMPv2c
; if SNMPv2 is used, set the community string used for the remote SNMP entity. Mandatory if SNMPv2c traps are used.
community=
; if SNMPv3 is used, specify which configured user should be used for sending traps (there must be a section named like the given value to trap_user)
; see the example bellow (section [userV3]) for configuring a SNMPv3 user
; the specified user will not allowed to interrogate this SNMP agent, it will only be used to send traps to the configured traps receiver
;trap_user=
;[userV3]
; Configure a section for a SNMPv3 user. The name of the user is the name of the section.
; To allow SNMPv3 interrogation, at least one SNMPv3 user must be configured
; authentication pass phrase. If it is not set, authentication will not be required
;auth_password=
; authentication method ( MD5 | SHA1 ) in case it is used.
;auth_protocol=MD5
; privacy pass phrase. If it is not set, encryption will not be required
;priv_password=
; privacy encryption method ( DES | AES). Default is DES.
;priv_protocol=DES
; user access level. Mandatory. Acceptable values are: readonly, readwrite, readcreate.
;access=

View File

@ -1272,11 +1272,14 @@ AC_CONFIG_FILES([packing/rpm/yate.spec
libs/ysig/Makefile
libs/ypbx/Makefile
libs/ymodem/Makefile
libs/yasn/Makefile
libs/ysnmp/Makefile
share/Makefile
share/scripts/Makefile
share/skins/Makefile
share/sounds/Makefile
share/help/Makefile
share/data/Makefile
conf.d/Makefile])
AC_CONFIG_FILES([yate-config],[chmod +x yate-config])
AC_CONFIG_FILES([run],[chmod +x run])

56
libs/yasn/Makefile.in Normal file
View File

@ -0,0 +1,56 @@
# Makefile
# This file holds the make rules for the libyasn
DEBUG :=
CXX := @CXX@ -Wall
AR := ar
DEFS :=
INCLUDES := -I@top_srcdir@ -I../.. -I@srcdir@
CFLAGS := @CFLAGS@ @MODULE_CPPFLAGS@ @INLINE_FLAGS@
LDFLAGS:= @LDFLAGS@ -L../.. -lyate
INCFILES := @top_srcdir@/yateclass.h @srcdir@/yateasn.h
PROGS=
LIBS = libyasn.a
OBJS = asn.o
LOCALFLAGS =
LOCALLIBS =
COMPILE = $(CXX) $(DEFS) $(DEBUG) $(INCLUDES) $(CFLAGS)
LINK = $(CXX) $(LDFLAGS)
prefix = @prefix@
exec_prefix = @exec_prefix@
# include optional local make rules
-include YateLocal.mak
.PHONY: all debug ddebug xdebug
all: $(LIBS) $(LIBD) $(PROGS)
debug:
$(MAKE) all DEBUG=-g3 MODSTRIP=
ddebug:
$(MAKE) all DEBUG='-g3 -DDEBUG' MODSTRIP=
xdebug:
$(MAKE) all DEBUG='-g3 -DXDEBUG' MODSTRIP=
.PHONY: strip
strip: all
strip --strip-debug --discard-locals $(PROGS)
.PHONY: clean
clean:
@-$(RM) $(PROGS) $(LIBS) $(OBJS) core 2>/dev/null
%.o: @srcdir@/%.cpp $(INCFILES)
$(COMPILE) -c $<
Makefile: @srcdir@/Makefile.in ../../config.status
cd ../.. && ./config.status
libyasn.a: $(OBJS)
$(AR) rcs $@ $^

1431
libs/yasn/asn.cpp Normal file

File diff suppressed because it is too large Load Diff

938
libs/yasn/yateasn.h Normal file
View File

@ -0,0 +1,938 @@
/**
* yateasn.h
* This file is part of the YATE Project http://YATE.null.ro
*
* ASN.1 Library
*
* Yet Another Telephony Engine - a fully featured software PBX and IVR
* Copyright (C) 2004-2010 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 __YATEASN_H
#define __YATEASN_H
#include <yatengine.h>
#ifdef _WINDOWS
#ifdef LIBYASN_EXPORTS
#define YASN_API __declspec(dllexport)
#else
#ifndef LIBYASN_STATIC
#define YASN_API __declspec(dllimport)
#endif
#endif
#endif /* _WINDOWS */
#ifndef YASN_API
#define YASN_API
#endif
namespace TelEngine {
#define ASN_LONG_LENGTH 0x80
#define ASN_BIT8 0x80
#define ASN_EXTENSION_ID 31
#define IS_EXTENSION_ID(byte) (((byte) & ASN_EXTENSION_ID) == ASN_EXTENSION_ID)
class AsnObject;
class AsnValue;
class AsnMibTree;
class ASNObjId;
class ASNLib;
class ASNError;
/**
* Helper class for operations with octet strings. Helps with conversions from String to/from DataBlock
* @short Helper class for operations with octet strings
*/
class OctetString : public DataBlock
{
public:
/**
* Get the String contained in this buffer
* @return String containing the internal data
*/
inline String getString()
{
String str((const char*)data(),length());
return str;
}
inline DataBlock& operator=(const String& value)
{
clear();
append(value);
return *this;
}
inline DataBlock& operator=(const DataBlock& value)
{
clear();
append(value);
return *this;
}
/**
* Get the content of the buffer in form of a hexified string
* @return Hexified string
*/
inline const String toHexString() const
{
String str;
str = str.hexify(data(),length());
return str;
}
/**
* Builed this DataBlock from a hexified string
* @return The DataBlock built from the given hexified string
*/
inline DataBlock& fromHexString(const String& value)
{
unHexify(value,value.length());
return *this;
}
};
/**
* Abstract class implemented by all ASN.1 type objects
* @short Base Class for ASN.1 objects
*/
class YASN_API AsnObject : public GenObject {
YCLASS(AsnObject, GenObject)
public:
/**
* Constructor
*/
inline AsnObject()
{}
/**
* Constructor
* @param data Data from which the object is built
* @param len Length of the given data
*/
AsnObject(void* data, int len)
{}
/**
* Destructor
*/
virtual inline ~AsnObject()
{}
/**
* Function to decode the parameters of this object from given data
* @param data DataBlock from which the object is decoded
*/
virtual int decode(DataBlock& data) = 0;
/**
* Function to encode this object into a datablock
* @param data The DataBlock in which the object should be encoded
*/
virtual int encode(DataBlock& data) = 0;
/**
* Function for obtaining this object's data
* @param params NamedList in which this object's data should be put
*/
virtual void getParams(NamedList* params) = 0;
/**
* Function for setting this object's data
* @param params NamedList containing the values to which this object's data should be set
*/
virtual void setParams(NamedList* params) = 0;
};
/**
* Class wrapper for different types of ASN.1 values
* @short An ASN.1 value
*/
class YASN_API AsnValue : public GenObject {
YCLASS(AsnValue, GenObject)
public:
/**
* Type of value
*/
enum ValType {
INTEGER = 1,
STRING = 2,
OBJECT_ID = 3,
IPADDRESS = 4,
COUNTER = 5,
TIMETICKS = 6,
ARBITRARY = 7,
BIG_COUNTER = 8,
UNSIGNED_INTEGER = 9
};
/**
* Constructor
*/
inline AsnValue()
: m_type(0), m_data("")
{}
/**
* Constructor
* @param value Object value
* @param type AsnValue type, default is String
*/
inline AsnValue(const String& value, int type = STRING)
: m_type(type), m_data(value)
{ }
/**
* Destructor
*/
virtual inline ~AsnValue()
{}
/**
* Get the value in the form of a string
* @return String containing the internal data
*/
inline String getValue()
{ return m_data;}
/**
* Get the type of the data so that we know how to interpret it
* @return The type of the data
*/
inline int type()
{ return m_type;}
/**
* Assign operator
*/
inline AsnValue& operator=( AsnValue* val)
{
if (!val)
return *this;
m_data = val->getValue();
m_type = val->type();
return *this;
}
/**
* Assign operator
*/
inline AsnValue& operator=( AsnValue val)
{
m_data = val.getValue();
m_type = val.type();
return *this;
}
/**
* Set data
* @param data The data to which the internal data will be set
*/
inline void setValue(const String& data)
{ m_data.clear();m_data = data; }
/**
* Set data type
* @param type The type assigned
*/
inline void setType(int type)
{ m_type = type; }
private:
int m_type;
String m_data;
};
/**
* Class describing an ASN.1 OID
*/
class YASN_API AsnMib : public GenObject {
YCLASS(AsnMib, GenObject)
public:
/**
* Access levels
*/
enum Access {
notAccessible = 0,
accessibleForNotify = 1,
readOnly = 2,
readWrite = 3,
readCreate = 4
};
/**
* Constructor
*/
inline AsnMib()
: m_access(""), m_accessVal(0), m_index(0)
{}
/**
* Constructor
* @param params NamedList containing data for building this object, it should contain name, access level, value type
*/
AsnMib(NamedList* params);
/**
* Destructor
*/
inline ~AsnMib()
{}
/**
* Get OID access level in string form
* @return String containing the access level for this OID. It's one of the following values : not-accessible, read-only, read-write,
read-create, accessible-for-notify.
*/
inline String& getAccess()
{ return m_access;}
/**
* Get OID access level
* @return String containing the access level for this OID. It's one of the following values : not-accessible, read-only, read-write,
read-create, accessible-for-notify.
*/
inline int getAccessValue()
{ return m_accessVal;}
/**
* Get the name of this OID
* @return Name of the OID
*/
inline String& getName()
{ return m_name;}
/**
* Get the oid
* @return The OID
*/
inline String getOID()
{ String str = ".";
str += m_index;
return m_oid + str;}
/**
* Get the type of the value of this OID
* @return String containing the type of value
*/
inline String& getType()
{ return m_type;}
/**
* Get the revision of this OID
* @return String containing the revision string
*/
inline String& getRevision()
{ return m_revision; }
/**
* Get the string representation of this OID
* @return String representation of this OID
*/
inline const String& toString() const
{ return m_oid;}
/**
* Set the index of an OID in case this OID is part of a table.
* @param ind Given index
*/
inline void setIndex(unsigned int ind)
{ m_index = ind;}
/**
* Obtain the index of this OID
* @return This OID's index in the OID table
*/
inline unsigned int index()
{ return m_index;}
/**
* Compare this object ID with another
* @param mib The object ID with which this object should be compared
* @return 0 if they're equal, -1 if this object is less lexicographically then the given parameter, 1 if it's greater
*/
int compareTo(AsnMib* mib);
/**
* Get the parent object ID of this object
* @return String version of the parent ID
*/
inline String getParent()
{
int pos = m_oid.rfind('.');
return m_oid.substr(0,pos);
}
private:
String m_name;
String m_oid;
String m_access;
int m_accessVal;
String m_type;
String m_revision;
int size;
int maxVal;
int minVal;
unsigned int m_index;
static TokenDict s_access[];
};
/**
* Tree of OIDs.
*/
class YASN_API AsnMibTree : public GenObject {
YCLASS(AsnMibTree, GenObject)
public:
/**
* Constructor
*/
inline AsnMibTree()
{}
/**
* Constructor
* @param fileName File from which the tree is to be built
*/
AsnMibTree(const String& fileName);
/**
* Destructor
*/
virtual ~AsnMibTree();
/**
* Find a MIB object given the object id
* @param id The object id
* @return A pointer to the MIB with the searched object id, 0 if not found
*/
AsnMib* find(const ASNObjId& id);
/**
* Find a MIB given the MIB name
* @param name The name of the MIB object
* @return A pointer to the MIB with the searched object id, 0 if not found
*/
AsnMib* find(const String& name);
/**
* Find the next MIB object in the tree
* @param id Object id of the current MIB object
* @return A pointer to the next MIB object in the tree, 0 if there is no next
*/
AsnMib* findNext(const ASNObjId& id);
/**
* Get access level for the given object id
* @param oid Object id for which the access level is required
* @return Enum value describing the access level required for this object
*/
int getAccess(const ASNObjId& oid);
/**
* Build the tree of MIB objects
*/
void buildTree();
/**
* Find the module revision of which this OID is part of
* @param name Name of the OID
* @return String value of the module revision
*/
String findRevision(const String& name);
private:
Configuration m_treeConf;
ObjList m_mibs;
};
/**
* Class for holding only an OID
*/
class YASN_API ASNObjId : public GenObject {
YCLASS(ASNObjId, GenObject)
public:
/**
* Constructor
*/
ASNObjId();
/**
* Constructor
* @param val OID value in string format
*/
ASNObjId(const String& val);
/**
* Constructor
* @param name Name of the OID
* @param val OID value in string format
*/
ASNObjId(const String& name, const String& val);
/**
* Constructor
* @param mib Mib used for creating this OID
*/
ASNObjId(AsnMib* mib);
/**
* Destructor
*/
~ASNObjId();
/**
* Assign operator from a string value
*/
ASNObjId& operator=(const String& val);
/**
* Assign operator from a const char* value
*/
ASNObjId& operator=(const char* val);
/**
* Transform the value of this OID from a string value to a sequence of numbers
*/
void toDataBlock();
/**
* Get the sequence form of the OID
* @return Datablock sequence of ids
*/
DataBlock getIds();
/**
* String representation of the OID
*/
inline const String& toString() const
{ return m_value; }
/**
* Get the name of the OID
* @return String representation of the name
*/
inline const String& getName() const
{ return m_name; }
/**
* Set the OID value
* @param value OID value
*/
inline void setValue(const String& value)
{ m_value = value; toDataBlock();}
private:
String m_value;
String m_name;
DataBlock m_ids;
};
/**
* Class ASNLib
* @short Class containing functions for decoding/encoding ASN.1 basic data types
*/
class YASN_API ASNLib {
public:
/**
* ASN.1 Type tags
*/
enum TypeTag {
UNIVERSAL = 0x00,
BOOLEAN = 0x01,
INTEGER = 0x02,
BIT_STRING = 0x03,
OCTET_STRING = 0x04,
NULL_ID = 0x05,
OBJECT_ID = 0x06,
REAL = 0x09, //not implemented
UTF8_STR = 0x0c,
SEQUENCE = 0x30,
SET = 0x31,
NUMERIC_STR = 0x12,
PRINTABLE_STR = 0x13,
IA5_STR = 0x16,
UTC_TIME = 0x17,
GENERALIZED_TIME = 0x18,
VISIBLE_STR = 0x1a,
GENERAL_STR = 0x1b, // not implemented
UNIVERSAL_STR = 0x1c, // not implemented
CHARACTER_STR = 0x1d, // not implemented
BMP_STR = 0x1e, // not implemented
CHOICE = 0x1f, // does not have a value
DEFINED = 0x2d
};
// values not implemented
// 10 ENUMERATED
// 11 EMBEDDED PDV
// 13 RELATIVE-OID
// 20 TeletexString, T61String
// 21 VideotexString
// 25 GraphicString
// 27 GeneralString
// 28 UniversalString
// 29 CHARACTER STRING
// 30 BMPString
/**
* Error types
*/
enum Error {
InvalidLengthOrTag = -1,
ConstraintBreakError = -2,
ParseError,
InvalidContentsError
};
/**
* Constructor
*/
ASNLib();
/**
* Destructor
*/
~ASNLib();
/**
* Decode the length of the block data containing the ASN.1 type data
* @param data Input block from which to extract the length
* @return The length of the data block containing data, -1 if it couldn't be decoded
*/
static int decodeLength(DataBlock& data);
/**
* Decode a boolean value from the encoded data
* @param data Input block from which the boolean value should be extracted
* @param val Pointer to a boolean to be filled with the decoded value
* @param tagCheck Flag for indicating if in the process of decoding the value the presence of the ASN.1 tag for boolean (0x01) should be verified
* @return Length of data consumed from the input data it the decoding was successful, -1 if the boolean value could not be decoded
*/
static int decodeBoolean(DataBlock& data, bool* val, bool tagCheck);
/**
* Decode an integer value from the encoded data
* @param data Input block from which the integer value should be extracted
* @param intVal Integer to be filled with the decoded value
* @param bytes Width of the decoded integer field
* @param tagCheck Flag for indicating if in the process of decoding the value the presence of the ASN.1 tag for integer (0x02) should be verified
* @return Length of data consumed from the input data it the decoding was successful, -1 if the integer value could not be decoded
*/
static int decodeInteger(DataBlock& data, u_int64_t& intVal, unsigned int bytes, bool tagCheck);
/**
* Decode an unsigned integer value from the encoded data - helper function for casting from u_int64_t to u_int8_t in case of size constraints
* @param data Input block from which the integer value should be extracted
* @param intVal Integer to be filled with the decoded value
* @param tagCheck Flag for indicating if in the process of decoding the value the presence of the ASN.1 tag for integer (0x02) should be verified
* @return Length of data consumed from the input data it the decoding was successful, -1 if the integer value could not be decoded
*/
static int decodeUINT8(DataBlock& data, u_int8_t* intVal, bool tagCheck);
/**
* Decode an unsigned integer value from the encoded data - helper function for casting from u_int64_t to u_int16_t in case of size constraints
* @param data Input block from which the integer value should be extracted
* @param intVal Integer to be filled with the decoded value
* @param tagCheck Flag for indicating if in the process of decoding the value the presence of the ASN.1 tag for integer (0x02) should be verified
* @return Length of data consumed from the input data it the decoding was successful, -1 if the integer value could not be decoded
*/
static int decodeUINT16(DataBlock& data, u_int16_t* intVal, bool tagCheck);
/**
* Decode an unsigned integer value from the encoded data - helper function for casting from u_int64_t to u_int32_t in case of size constraints
* @param data Input block from which the integer value should be extracted
* @param intVal Integer to be filled with the decoded value
* @param tagCheck Flag for indicating if in the process of decoding the value the presence of the ASN.1 tag for integer (0x02) should be verified
* @return Length of data consumed from the input data it the decoding was successful, -1 if the integer value could not be decoded
*/
static int decodeUINT32(DataBlock& data, u_int32_t* intVal, bool tagCheck);
/**
* Decode an unsigned integer value from the encoded data - helper function for casting in case of size constraints
* @param data Input block from which the integer value should be extracted
* @param intVal Integer to be filled with the decoded value
* @param tagCheck Flag for indicating if in the process of decoding the value the presence of the ASN.1 tag for integer (0x02) should be verified
* @return Length of data consumed from the input data it the decoding was successful, -1 if the integer value could not be decoded
*/
static int decodeUINT64(DataBlock& data, u_int64_t* intVal, bool tagCheck);
/**
* Decode an integer value from the encoded data - helper function for casting from u_int64_t to int8_t in case of size constraints
* @param data Input block from which the integer value should be extracted
* @param intVal Integer to be filled with the decoded value
* @param tagCheck Flag for indicating if in the process of decoding the value the presence of the ASN.1 tag for integer (0x02) should be verified
* @return Length of data consumed from the input data it the decoding was successful, -1 if the integer value could not be decoded
*/
static int decodeINT8(DataBlock& data, int8_t* intVal, bool tagCheck);
/**
* Decode an integer value from the encoded data - helper function for casting from u_int64_t to int16_t in case of size constraints
* @param data Input block from which the integer value should be extracted
* @param intVal Integer to be filled with the decoded value
* @param tagCheck Flag for indicating if in the process of decoding the value the presence of the ASN.1 tag for integer (0x02) should be verified
* @return Length of data consumed from the input data it the decoding was successful, -1 if the integer value could not be decoded
*/
static int decodeINT16(DataBlock& data, int16_t* intVal, bool tagCheck);
/**
* Decode an integer value from the encoded data - helper function for casting from u_int64_t to int32_t in case of size constraints
* @param data Input block from which the integer value should be extracted
* @param intVal Integer to be filled with the decoded value
* @param tagCheck Flag for indicating if in the process of decoding the value the presence of the ASN.1 tag for integer (0x02) should be verified
* @return Length of data consumed from the input data it the decoding was successful, -1 if the integer value could not be decoded
*/
static int decodeINT32(DataBlock& data, int32_t* intVal, bool tagCheck);
/**
* Decode an integer value from the encoded data - helper function for casting in case of size constraints
* @param data Input block from which the integer value should be extracted
* @param intVal Integer to be filled with the decoded value
* @param tagCheck Flag for indicating if in the process of decoding the value the presence of the ASN.1 tag for integer (0x02) should be verified
* @return Length of data consumed from the input data it the decoding was successful, -1 if the integer value could not be decoded
*/
static int decodeINT64(DataBlock& data, int64_t* intVal, bool tagCheck);
/**
* Decode a bitstring value from the encoded data
* @param data Input block from which the bitstring value should be extracted
* @param val String to be filled with the decoded value
* @param tagCheck Flag for indicating if in the process of decoding the value the presence of the ASN.1 tag for integer (0x03) should be verified
* @return Length of data consumed from the input data it the decoding was successful, -1 if the integer value could not be decoded
*/
static int decodeBitString(DataBlock& data, String* val, bool tagCheck);
/**
* Decode a string value from the encoded data
* @param data Input block from which the octet string value should be extracted
* @param strVal String to be filled with the decoded value
* @param tagCheck Flag for indicating if in the process of decoding the value the presence of the ASN.1 tag for integer (0x04) should be verified
* @return Length of data consumed from the input data it the decoding was successful, -1 if the integer value could not be decoded
*/
static int decodeOctetString(DataBlock& data, OctetString* strVal, bool tagCheck);
/**
* Decode a null value from the encoded data
* @param data Input block from which the null value should be extracted
* @param tagCheck Flag for indicating if in the process of decoding the value the presence of the ASN.1 tag for integer (0x05) should be verified
* @return Length of data consumed from the input data it the decoding was successful, -1 if the integer value could not be decoded
*/
static int decodeNull(DataBlock& data, bool tagCheck);
/**
* Decode an object id value from the encoded data
* @param data Input block from which the OID value should be extracted
* @param obj ASNObjId to be filled with the decoded value
* @param tagCheck Flag for indicating if in the process of decoding the value the presence of the ASN.1 tag for integer (0x06) should be verified
* @return Length of data consumed from the input data it the decoding was successful, -1 if the integer value could not be decoded
*/
static int decodeOID(DataBlock& data, ASNObjId* obj, bool tagCheck);
/**
* Decode a real value from the encoded data - not implemented
* @param data Input block from which the real value should be extracted
* @param realVal Float to be filled with the decoded value
* @param tagCheck Flag for indicating if in the process of decoding the value the presence of the ASN.1 tag for integer (0x09) should be verified
* @return Length of data consumed from the input data it the decoding was successful, -1 if the integer value could not be decoded
*/
static int decodeReal(DataBlock& data, float* realVal, bool tagCheck);
/**
* Decode other types of ASN.1 strings from the encoded data (NumericString, PrintableString, VisibleString, IA5String)
* @param data Input block from which the string value should be extracted
* @param str String to be filled with the decoded value
* @param type Integer to be filled with the value indicating which type of string has been decoded
* @param tagCheck Flag for indicating if in the process of decoding the value the presence of the ASN.1 tag should be verified
* @return Length of data consumed from the input data it the decoding was successful, -1 if the integer value could not be decoded
*/
static int decodeString(DataBlock& data, String* str, int* type, bool tagCheck);
/**
* Decode an UTF8 string from the encoded data
* @param data Input block from which the string value should be extracted
* @param str String to be filled with the decoded value
* @param tagCheck Flag for indicating if in the process of decoding the value the presence of the ASN.1 tag (0x0c) should be verified
* @return Length of data consumed from the input data it the decoding was successful, -1 if the integer value could not be decoded
*/
static int decodeUtf8(DataBlock& data, String* str, bool tagCheck);
/**
* Decode a GeneralizedTime value from the encoded data
* @param data Input block from which the value should be extracted
* @param time Integer to be filled with time in seconds since epoch
* @param fractions Integer to be filled with fractions of a second
* @param utc Flag indicating if the decode time value represent local time or UTC time
* @param tagCheck Flag for indicating if in the process of decoding the value the presence of the ASN.1 tag (0x18) should be verified
* @return Length of data consumed from the input data it the decoding was successful, -1 if the integer value could not be decoded
*/
static int decodeGenTime(DataBlock& data, unsigned int* time, unsigned int* fractions, bool* utc, bool tagCheck);
/**
* Decode a UTC time value from the encoded data
* @param data Input block from which the value should be extracted
* @param time Integer to be filled with time in seconds since epoch
* @param tagCheck Flag for indicating if in the process of decoding the value the presence of the ASN.1 tag (0x17) should be verified
* @return Length of data consumed from the input data it the decoding was successful, -1 if the integer value could not be decoded
*/
static int decodeUTCTime(DataBlock& data, unsigned int* time, bool tagCheck);
/**
* Decode a block of arbitrary data
* @param data Input block from which the value should be extracted
* @param val DataBlock in which the data shoulb be copied
* @param tagCheck Flag for indicating if in the process of decoding the value the presence of the ASN.1 should be verified
* @return Length of data consumed from the input data it the decoding was successful, -1 if the integer value could not be decoded
*/
static int decodeAny(DataBlock data, DataBlock* val, bool tagCheck);
/**
* Decode the header of an ASN.1 sequence ( decodes the tag and the length of the sequence)
* @param data Input block from which the header should be extracted
* @param tagCheck Flag for indicating if in the process of decoding the value the presence of the ASN.1 (0x30) should be verified
* @return Length of data consumed from the input data it the decoding was succesful, -1 if the integer value could not be decoded
*/
static int decodeSequence(DataBlock& data, bool tagCheck);
/**
* Decode the header of an ASN.1 set ( decodes the tag and the length of the sequence)
* @param data Input block from which the header should be extracted
* @param tagCheck Flag for indicating if in the process of decoding the value the presence of the ASN.1 (0x31) should be verified
* @return Length of data consumed from the input data it the decoding was succesful, -1 if the integer value could not be decoded
*/
static int decodeSet(DataBlock& data, bool tagCheck);
/**
* Encode the length of the given data
* @param data The data for which the length should be encoded
* @return The data block which now contains the length encoding
*/
static DataBlock buildLength(DataBlock& data);
/**
* Encode the given boolean value
* @param val The boolean value to encode
* @param tagCheck Flag to specify if the boolean type tag should be inserted in the encoding
* @return The data block encoding of the value
*/
static DataBlock encodeBoolean(bool val, bool tagCheck);
/**
* Encode the given integer value
* @param intVal The integer value to encode
* @param tagCheck Flag to specify if the integer type tag should be inserted in the encoding
* @return The data block encoding of the value
*/
static DataBlock encodeInteger(u_int64_t intVal, bool tagCheck);
/**
* Encode the given octet string value
* @param strVal The octet string value to encode
* @param tagCheck Flag to specify if the octet string type tag should be inserted in the encoding
* @return The data block encoding of the value
*/
static DataBlock encodeOctetString(OctetString strVal, bool tagCheck);
/**
* Encode a null value
* @param tagCheck Flag to specify if the null tag should be inserted in the encoding
* @return The data block encoding of the value
*/
static DataBlock encodeNull(bool tagCheck);
/**
* Encode the given bitstring value
* @param val The bitstring value to encode
* @param tagCheck Flag to specify if the type tag should be inserted in the encoding
* @return The data block encoding of the value
*/
static DataBlock encodeBitString(String val, bool tagCheck);
/**
* Encode the given OID value
* @param obj The OID value to encode
* @param tagCheck Flag to specify if the type tag should be inserted in the encoding
* @return The data block encoding of the value
*/
static DataBlock encodeOID(ASNObjId obj, bool tagCheck);
/**
* Encode the given real value - not implemented
* @param val The real value to encode
* @param tagCheck Flag to specify if the type tag should be inserted in the encoding
* @return The data block encoding of the value
*/
static DataBlock encodeReal(float val, bool tagCheck);
/**
* Encode the given string value to NumericString, PrintableString, IA5String, VisibleString
* @param str The string value to encode
* @param type The type of the encoding
* @param tagCheck Flag to specify if the type tag should be inserted in the encoding
* @return The data block encoding of the value
*/
static DataBlock encodeString(String str, int type, bool tagCheck);
/**
* Encode the UTF8 string value
* @param str The string value to encode
* @param tagCheck Flag to specify if the type tag should be inserted in the encoding
* @return The data block encoding of the value
*/
static DataBlock encodeUtf8(String str, bool tagCheck);
/**
* Encode the given time value into a GeneralizedTime format
* @param time Time in seconds since epoch to encode
* @param fractions Fractions of a seconds to encode
* @param tagCheck Flag to specify if the type tag should be inserted in the encoding
* @return The data block encoding of the value
*/
static DataBlock encodeGenTime(unsigned int time, unsigned int fractions, bool tagCheck);
/**
* Encode the given time value into an UTCTime format
* @param time Time in seconds since epoch to encode
* @param tagCheck Flag to specify if the type tag should be inserted in the encoding
* @return The data block encoding of the value
*/
static DataBlock encodeUTCTime(unsigned int time, bool tagCheck);
/**
* Encode an arbitrary block a data
* @param data data
* @param tagCheck Flag to specify if the type tag should be inserted in the encoding
* @return The data block encoding of the value
*/
static DataBlock encodeAny(DataBlock data, bool tagCheck);
/**
* Encode the header for a sequence
* @param data Sequence data for which the header is encoded
* @param tagCheck Flag to specify if the ype tag should be inserted in the encoding
* @return The length of the data block length encoding
*/
static int encodeSequence(DataBlock& data, bool tagCheck);
/**
* Encode the header for a set
* @param data Sequence data for which the header is encoded
* @param tagCheck Flag to specify if the type tag should be inserted in the encoding
* @return The length of the data block length encoding
*/
static int encodeSet(DataBlock& data, bool tagCheck);
};
}
#endif /* __YATEASN_H */
/* vi: set ts=8 sw=4 sts=4 noet: */

View File

@ -2151,6 +2151,13 @@ public:
JBClientStream* create(const String& account, const NamedList& params,
const String& name = String::empty());
/**
* Retrieve the list of streams of a given type
* @param list The destination list to set
* @param type Stream type
*/
virtual void getStreamList(RefPointer<JBStreamSetList>& list, int type);
protected:
/**
* Add a stream to one of the stream lists
@ -2172,13 +2179,6 @@ protected:
*/
virtual void stopStreamSets(bool waitTerminate = true);
/**
* Retrieve the list of streams of a given type
* @param list The destination list to set
* @param type Stream type
*/
virtual void getStreamList(RefPointer<JBStreamSetList>& list, int type);
JBStreamSetList* m_receive; // Streams receive list
JBStreamSetList* m_process; // Streams process list
};

View File

@ -394,6 +394,8 @@ MGCPEvent* MGCPTransaction::checkTimeout(u_int64_t time)
}
m_timeout = (state() == Initiated || state() == Trying);
if (m_timeout)
engine()->timeout(this);
return terminate();
}

View File

@ -1014,6 +1014,13 @@ public:
static inline int defaultPort(bool gateway)
{ return gateway ? 2427 : 2727; }
/**
* Handle a transaction that has timed out
* @param tr The transaction that has timed out
*/
virtual void timeout(MGCPTransaction* tr)
{ }
/**
* The list of commands defined in RFC 3435
*/

View File

@ -184,6 +184,7 @@ void RTPReceiver::rtpData(const void* data, int len)
Debug(DebugWarn,"RTP Received SSRC %08X but expecting %08X [%p]",
ss,m_ssrc,this);
}
m_wrongSSRC++;
return;
}
// SSRC accepted, sync sequence and resync the timestamp offset
@ -196,6 +197,8 @@ void RTPReceiver::rtpData(const void* data, int len)
// substraction with overflow
int16_t ds = seq - m_seq;
if (ds != 1)
m_seqLost++;
// check if we received duplicate or delayed packet
// be much more tolerant when authenticating as we cannot resync
if ((ds <= 0) || ((ds > SEQ_DESYNC_COUNT) && !secPtr)) {
@ -212,6 +215,7 @@ void RTPReceiver::rtpData(const void* data, int len)
m_ts = ts - m_tsLast;
m_seqCount = 0;
m_warn = true;
m_syncLost++;
// drop this packet, next packet will come in correctly
return;
}
@ -377,6 +381,15 @@ bool RTPReceiver::rtpCheckIntegrity(const unsigned char* data, int len, const vo
: true;
}
void RTPReceiver::stats(NamedList& stat) const
{
if (m_session)
stat.setParam("remoteip",m_session->UDPSession::transport()->remoteAddr().host());
stat.setParam("lostpkts",String(m_ioLostPkt));
stat.setParam("synclost",String(m_syncLost));
stat.setParam("wrongssrc",String(m_wrongSSRC));
stat.setParam("seqslost",String(m_seqLost));
}
RTPSender::RTPSender(RTPSession* session, bool randomTs)
: RTPBaseIO(session), m_evTime(0), m_padding(0)
@ -551,6 +564,9 @@ void RTPSender::rtpAddIntegrity(const unsigned char* data, int len, unsigned cha
m_secure->rtpAddIntegrity(data,len,authData);
}
void RTPSender::stats(NamedList& stat) const
{
}
UDPSession::UDPSession()
: m_transport(0), m_timeoutTime(0), m_timeoutInterval(0)
@ -872,6 +888,15 @@ void RTPSession::setReports(int interval)
m_reportTime = 0;
}
void RTPSession::getStats(NamedList& stats) const
{
if (m_send)
m_send->stats(stats);
if (m_recv)
m_recv->stats(stats);
stats.setParam("wrongsrc",String(m_wrongSrc));
}
static void store32(unsigned char* buf, unsigned int& len, u_int32_t val)
{
buf[len++] = (unsigned char)(val >> 24);
@ -945,6 +970,11 @@ void RTPSession::sendRtcpBye()
static_cast<RTPProcessor*>(m_transport)->rtcpData(buf,8);
}
void RTPSession::incWrongSrc()
{
Debug(DebugAll,"RTPSession::incWrongSrc() [%p]",this);
m_wrongSrc++;
}
UDPTLSession::UDPTLSession(u_int16_t maxLen, u_int8_t maxSec)
: m_rxSeq(0xffff), m_txSeq(0xffff),

View File

@ -126,7 +126,7 @@ void RTPGroup::setMinSleep(int msec)
RTPProcessor::RTPProcessor()
: m_group(0)
: m_wrongSrc(0), m_group(0)
{
DDebug(DebugAll,"RTPProcessor::RTPProcessor() [%p]",this);
}
@ -218,6 +218,8 @@ void RTPTransport::timerTick(const Time& when)
if (m_monitor)
m_monitor->rtpData(buf,len);
}
else
m_processor->incWrongSrc();
}
m_rtpSock.timerTick(when);
}

View File

@ -105,6 +105,19 @@ public:
*/
virtual void getStats(String& stats) const;
/**
* Increase the counter for number of RTP packets received from a wrong source
*/
virtual inline void incWrongSrc()
{ }
/**
* Get the number of RTP packets that were received from a wrong source
* @return Number of RTP packets received from a wrong source
*/
inline unsigned int wrongSrc()
{ return m_wrongSrc; }
protected:
/**
* Set a new RTP group for this processor
@ -118,6 +131,8 @@ protected:
*/
virtual void timerTick(const Time& when) = 0;
unsigned int m_wrongSrc;
private:
RTPGroup* m_group;
};
@ -578,7 +593,8 @@ public:
inline RTPReceiver(RTPSession* session = 0)
: RTPBaseIO(session),
m_ioLostPkt(0), m_dejitter(0),
m_seqSync(0), m_seqCount(0), m_warn(true)
m_seqSync(0), m_seqCount(0), m_warn(true),
m_seqLost(0), m_wrongSSRC(0), m_syncLost(0)
{ }
/**
@ -662,6 +678,12 @@ public:
*/
virtual void rtpNewSSRC(u_int32_t newSsrc, bool marker);
/**
* Retrieve the statistical data from this receiver in a NamedList. Reset all the data.
* @param NamedList to populate with the values for different counters
*/
virtual void stats(NamedList& stat) const;
protected:
/**
* Method called periodically to finish lingering events
@ -706,6 +728,9 @@ private:
u_int16_t m_seqSync;
u_int16_t m_seqCount;
bool m_warn;
unsigned int m_seqLost;
unsigned int m_wrongSSRC;
unsigned int m_syncLost;
};
/**
@ -786,6 +811,12 @@ public:
*/
bool padding(int chunk);
/**
* Retrieve the statistical data from this receiver in a NamedList. Reset all the data.
* @param NamedList to populate with the values for different counters
*/
virtual void stats(NamedList& stat) const;
protected:
/**
* Method called periodically to send events and buffered data
@ -1219,6 +1250,17 @@ public:
*/
void setReports(int interval);
/**
* Put the collected statistical data
* @param stats NamedList to populate with the data
*/
virtual void getStats(NamedList& stats) const;
/**
* Increase the counter for number of RTP packets received from a wrong source
*/
virtual void incWrongSrc();
protected:
/**
* Method called periodically to push any asynchronous data or statistics

View File

@ -129,10 +129,11 @@ void* SignallingFactory::buildInternal(const String& type, const NamedList* name
SignallingComponent::SignallingComponent(const char* name, const NamedList* params)
: m_engine(0)
: m_engine(0), m_compType("unknown")
{
if (params) {
name = params->getValue("debugname",name);
m_compType = params->getValue("type",m_compType);
debugLevel(params->getIntValue("debuglevel",-1));
}
DDebug(engine(),DebugAll,"Component '%s' created [%p]",name,this);
@ -237,6 +238,15 @@ unsigned long SignallingComponent::tickSleep(unsigned long usec) const
return m_engine ? m_engine->tickSleep(usec) : 0;
}
void SignallingNotifier::notify(NamedList& notifs)
{
DDebug(DebugInfo,"SignallingNotifier::notify() [%p] stub",this);
}
void SignallingNotifier::cleanup()
{
DDebug(DebugInfo,"SignallingNotifier::cleanup() [%p] stub",this);
}
static SignallingEngine* s_self = 0;
@ -376,6 +386,14 @@ bool SignallingEngine::remove(const String& name)
return true;
}
void SignallingEngine::notify(SignallingComponent* component, NamedList notifs)
{
if (!(m_notifier && component))
return;
Debug(this,DebugAll,"Engine [%p] sending notify from '%s' [%p]",this,component->toString().c_str(),component);
m_notifier->notify(notifs);
}
bool SignallingEngine::control(NamedList& params)
{
bool ok = false;

View File

@ -3693,7 +3693,15 @@ void SS7ISUP::notify(SS7Layer3* link, int sls)
if (!link)
return;
Lock mylock(this);
m_l3LinkUp = link->operational(-1);
// Ignore links not routing our remote point code
if ((unsigned int)-1 == link->getRoutePriority(m_type,m_remotePoint->pack(m_type)))
return;
bool linkTmp = m_l3LinkUp;
// Link is not operational
if (link->operational())
m_l3LinkUp = true;
else
m_l3LinkUp = false;
// Reset remote user part's availability state if supported
// Force UPT re-send
if (m_uptTimer.interval() && !m_l3LinkUp) {
@ -3705,6 +3713,13 @@ void SS7ISUP::notify(SS7Layer3* link, int sls)
link,link->toString().safe(),
(m_l3LinkUp ? "" : "not "),sls,
(m_userPartAvail ? "" : "un"));
if (linkTmp != m_l3LinkUp) {
NamedList params("");
params.addParam("type","trunk");
params.addParam("operational",String::boolText(m_l3LinkUp));
params.addParam("from",link->toString());
engine()->notify(this,params);
}
}
SS7MSU* SS7ISUP::buildMSU(SS7MsgISUP::Type type, unsigned char sio,

View File

@ -1174,6 +1174,16 @@ void SS7MTP3::notify(SS7Layer2* link)
if (cnt)
Debug(this,DebugNote,"Attempted to uninhibit/resume %u links [%p]",cnt,this);
SS7Layer3::notify(link ? link->sls() : -1);
NamedList notif("");
notif.addParam("from", toString());
notif.addParam("type","ss7-mtp3");
notif.addParam("operational",String::boolText(operational()));
notif.addParam("active",String(m_active));
notif.addParam("total",String(m_total));
notif.addParam("link", link ? link->toString() : "");
notif.addParam("linkup", link ? String::boolText(link->operational()) : "");
engine()->notify(this,notif);
}
}

View File

@ -2570,7 +2570,15 @@ bool ISDNQ931::sendMessage(ISDNQ931Message* msg, u_int8_t tei, String* reason)
void ISDNQ931::multipleFrameEstablished(u_int8_t tei, bool confirmation, bool timeout, ISDNLayer2* layer2)
{
l3Mutex().lock();
bool q921Tmp = m_q921Up;
m_q921Up = true;
if (m_q921Up != q921Tmp) {
NamedList p("");
p.addParam("type","isdn-q921");
p.addParam("operational",String::boolText(m_q921Up));
p.addParam("from",m_q921->toString());
engine()->notify(this,p);
}
DDebug(this,DebugNote,"'Established' %s TEI %u",
confirmation ? "confirmation" :"indication",tei);
endReceiveSegment("Data link is up");
@ -2590,7 +2598,15 @@ void ISDNQ931::multipleFrameEstablished(u_int8_t tei, bool confirmation, bool ti
void ISDNQ931::multipleFrameReleased(u_int8_t tei, bool confirmation, bool timeout, ISDNLayer2* layer2)
{
Lock lockLayer(l3Mutex());
bool q921Tmp = m_q921Up;
m_q921Up = false;
if (m_q921Up != q921Tmp) {
NamedList p("");
p.addParam("type","isdn-q921");
p.addParam("operational",String::boolText(m_q921Up));
p.addParam("from",m_q921->toString());
engine()->notify(this,p);
}
DDebug(this,DebugNote,"'Released' %s TEI %u. Timeout: %s",
confirmation ? "confirmation" :"indication",tei,String::boolText(timeout));
endReceiveSegment("Data link is down");

View File

@ -51,6 +51,7 @@ namespace TelEngine {
// Signalling classes
class SignallingDumper; // A generic data dumper
class SignallingDumpable; // A component that can dump data
class SignallingNotifier; // A signalling notifier
class SignallingTimer; // A signalling timer
class SignallingCounter; // A signalling counter
class SignallingFactory; // A signalling component factory
@ -350,6 +351,30 @@ private:
SignallingDumper* m_dumper;
};
/**
* Notifying class. Used to handle notifications.
* @short Notifier class
*/
class YSIG_API SignallingNotifier
{
public:
/**
* Destructor.
*/
inline ~SignallingNotifier()
{ cleanup(); }
/**
* Handle the received notifications
* @param notifs Received notifications
*/
virtual void notify(NamedList& notifs);
/**
* Handle necessary clean up
*/
virtual void cleanup();
};
/**
* Timer management class. Used to manage timeouts. The time is kept in miliseconds
* @short A signalling timer
@ -659,6 +684,13 @@ public:
inline int debugLevel(int level)
{ return (level >= 0) ? DebugEnabler::debugLevel(level) : DebugEnabler::debugLevel(); }
/**
* Return the type of this component
* @return A string version of the component type
*/
inline const String& componentType() const
{ return m_compType; }
protected:
/**
* Constructor with a default empty component name
@ -711,6 +743,7 @@ protected:
private:
SignallingEngine* m_engine;
String m_name;
String m_compType;
};
/**
@ -799,6 +832,13 @@ public:
*/
bool find(const SignallingComponent* component);
/**
* Handle notifications from a SignallingComponent
* @param component The SignallingComponent from which the notifications were received
* @param notifs The notifications sent by this SignallingComponent
*/
void notify(SignallingComponent* component, NamedList notifs);
/**
* Starts the worker thread that keeps components alive
* @param name Static name of the thread
@ -813,6 +853,23 @@ public:
*/
void stop();
/**
* Add to this engine a notifier object
* @param notifier The SignallingNotifier object to be added to the engine
*/
inline void setNotifier(SignallingNotifier* notifier)
{ m_notifier = notifier; }
/**
* Remove from this engine a notifier object
* @param notifier The SignallingNotifier object to be removed from the engine
*/
inline void removeNotifier(SignallingNotifier* notifier)
{
if (m_notifier == notifier)
m_notifier = 0;
}
/**
* Return a pointer to the worker thread
* @return Pointer to running worker thread or NULL
@ -863,6 +920,7 @@ protected:
private:
SignallingThreadPrivate* m_thread;
SignallingNotifier* m_notifier;
unsigned long m_usecSleep;
unsigned long m_tickSleep;
};
@ -7035,6 +7093,13 @@ public:
inline unsigned int linksActive() const
{ return m_active; }
/**
* Get a list of the links held by this linkset
* @return A list containing the links
*/
inline const ObjList* links() const
{ return &m_links; }
protected:
/**
* Detach all links and user. Destroys the object, disposes the memory

55
libs/ysnmp/Makefile.in Normal file
View File

@ -0,0 +1,55 @@
# Makefile
# This file holds the make rules for the libysnmp
DEBUG :=
CXX := @CXX@ -Wall
AR := ar
DEFS :=
INCLUDES := -I@top_srcdir@ -I../.. -I@top_srcdir@/libs/yasn -I@srcdir@
CFLAGS := @CFLAGS@ @MODULE_CPPFLAGS@ @INLINE_FLAGS@
LDFLAGS:= @LDFLAGS@ -L../yasn -lyasn -L../.. -lyate
INCFILES := @top_srcdir@/yateclass.h @top_srcdir@/libs/yasn/yateasn.h @srcdir@/yatesnmp.h
PROGS=
LIBS = libysnmp.a
OBJS = snmp.o
LOCALFLAGS =
LOCALLIBS =
COMPILE = $(CXX) $(DEFS) $(DEBUG) $(INCLUDES) $(CFLAGS)
LINK = $(CXX) $(LDFLAGS)
prefix = @prefix@
exec_prefix = @exec_prefix@
# include optional local make rules
-include YateLocal.mak
.PHONY: all debug ddebug xdebug
all: $(LIBS) $(LIBD) $(PROGS)
debug:
$(MAKE) all DEBUG=-g3 MODSTRIP=
ddebug:
$(MAKE) all DEBUG='-g3 -DDEBUG' MODSTRIP=
xdebug:
$(MAKE) all DEBUG='-g3 -DXDEBUG' MODSTRIP=
.PHONY: strip
strip: all
strip --strip-debug --discard-locals $(PROGS)
.PHONY: clean
clean:
@-$(RM) $(PROGS) $(LIBS) $(LIBD) $(OBJS) core 2>/dev/null
%.o: @srcdir@/%.cpp $(INCFILES)
$(COMPILE) -c $<
Makefile: @srcdir@/Makefile.in ../../config.status
cd ../.. && ./config.status
libysnmp.a: $(OBJS)
$(AR) rcs $@ $^

3005
libs/ysnmp/snmp.cpp Normal file

File diff suppressed because it is too large Load Diff

1184
libs/ysnmp/yatesnmp.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -62,6 +62,8 @@ PROGS := cdrbuild.yate cdrfile.yate regexroute.yate \
server/callcounters.yate \
server/dbwave.yate \
server/yradius.yate \
server/ysnmpagent.yate \
server/monitoring.yate \
server/sipfeatures.yate \
server/heartbeat.yate server/clustering.yate \
server/mgcpgw.yate server/mgcpca.yate \
@ -72,6 +74,7 @@ PROGS := cdrbuild.yate cdrfile.yate regexroute.yate \
server/analogdetect.yate \
client/jabberclient.yate \
callgen.yate analyzer.yate rmanager.yate msgsniff.yate
LIBS :=
DIRS := client server jabber qt4
@ -346,6 +349,10 @@ server/sipfeatures.yate: LOCALLIBS = -L../libs/yxml -lyatexml
zlibcompress.yate: LOCALFLAGS = $(ZLIB_INC)
zlibcompress.yate: LOCALLIBS = $(ZLIB_LIB)
server/ysnmpagent.yate: ../libs/yasn/libyasn.a ../libs/ysnmp/libysnmp.a
server/ysnmpagent.yate: LOCALFLAGS = -I@top_srcdir@/libs/yasn -I@top_srcdir@/libs/ysnmp
server/ysnmpagent.yate: LOCALLIBS = -L../libs/yasn -lyasn -L../libs/ysnmp -lysnmp
../libyatesig.so ../libs/ysig/libyatesig.a:
$(MAKE) -C ../libs/ysig
@ -378,3 +385,9 @@ zlibcompress.yate: LOCALLIBS = $(ZLIB_LIB)
../libs/ypbx/libyatepbx.a:
$(MAKE) -C ../libs/ypbx
../libs/yasn/libyasn.a:
$(MAKE) -C ../libs/yasn
../libs/ysnmp/libysnmp.a:
$(MAKE) -C ../libs/ysnmp

View File

@ -361,6 +361,9 @@ public:
// Check if this module handles a given protocol
inline bool canHandleProtocol(const String& proto)
{ return proto == "jabber"; }
// List accounts
void statusAccounts(String& retVal);
protected:
// Inherited methods
virtual bool received(Message& msg, int id);
@ -2136,8 +2139,12 @@ bool JBModule::received(Message& msg, int id)
if (!target)
return Module::received(msg,id);
// Handle: status jabberclient stream_name
statusModule(msg.retValue());
s_jabber->statusDetail(msg.retValue(),target);
if (target == "accounts")
statusAccounts(msg.retValue());
else {
statusModule(msg.retValue());
s_jabber->statusDetail(msg.retValue(),target);
}
msg.retValue() << "\r\n";
return true;
}
@ -2246,13 +2253,17 @@ bool JBModule::commandComplete(Message& msg, const String& partLine,
if (word != name())
return Module::commandComplete(msg,partLine,partWord);
getWord(line,word);
if (word == "accounts")
return false;
if (word) {
if (line)
return false;
s_jabber->completeStreamName(msg.retValue(),partWord);
}
else
else {
itemComplete(msg.retValue(),"accounts",partWord);
s_jabber->completeStreamName(msg.retValue(),partWord);
}
return true;
}
return Module::commandComplete(msg,partLine,partWord);
@ -2314,6 +2325,35 @@ bool JBModule::commandExecute(String& retVal, const String& line)
return true;
}
void JBModule::statusAccounts(String& retVal)
{
DDebug(this,DebugAll,"List the status of all accounts");
RefPointer<JBStreamSetList> list;
s_jabber->getStreamList(list,JBStream::c2s);
if (!list)
return;
String str = "";
list->lock();
for (ObjList* o = list->sets().skipNull(); o; o = o->skipNext()) {
JBStreamSet* set = static_cast<JBStreamSet*>(o->get());
for (ObjList* s = set->clients().skipNull(); s; s = s->skipNext()) {
JBClientStream* stream = static_cast<JBClientStream*>(s->get());
stream->lock();
str.append(stream->local().bare(),",");
str << "=Jabber|";
str << stream->stateName();
stream->unlock();
}
}
list->unlock();
list = 0;
if (retVal.null()) {
retVal << "module=" << name();
retVal << ",format=Protocol|Status;";
}
retVal << str;
}
}; // anonymous namespace
/* vi: set ts=8 sw=4 sts=4 noet: */

View File

@ -275,6 +275,8 @@ public:
virtual void statusParams(String& str);
void cleanup();
YateH323EndPoint* findEndpoint(const String& ep) const;
bool commandComplete(Message& msg, const String& partLine, const String& partWord);
void msgStatus(Message& msg);
private:
ObjList m_endpoints;
};
@ -282,6 +284,8 @@ private:
H323Process* s_process = 0;
static H323Driver hplugin;
static String s_statusCmd = "status";
class YateGatekeeperCall : public H323GatekeeperCall
{
PCLASSINFO(YateGatekeeperCall, H323GatekeeperCall);
@ -2340,6 +2344,12 @@ H323Driver::~H323Driver()
bool H323Driver::received(Message &msg, int id)
{
if (id == Status) {
String target = msg.getValue("module");
if (target && target.startsWith(name()) && !target.startsWith(prefix()))
msgStatus(msg);
return false;
}
bool ok = Driver::received(msg,id);
if (id == Halt)
cleanup();
@ -2442,6 +2452,7 @@ void H323Driver::initialize()
s_process = new H323Process;
installRelay(Progress);
installRelay(Route);
installRelay(Status);
Engine::install(new UserHandler);
}
int dbg = s_cfg.getIntValue("general","debug");
@ -2469,6 +2480,41 @@ void H323Driver::initialize()
}
}
bool H323Driver::commandComplete(Message& msg, const String& partLine, const String& partWord)
{
String cmd = s_statusCmd;
cmd << " " << name();
if (partLine == cmd)
itemComplete(msg.retValue(),"accounts",partWord);
else
return Driver::commandComplete(msg,partLine,partWord);
return false;
}
void H323Driver::msgStatus(Message& msg)
{
String str = msg.getValue("module");
while (str.startSkip(name())) {
str.trimBlanks();
if (str.null())
break;
if (str.startSkip("accounts")) {
msg.retValue().clear();
msg.retValue() << "module=" << name();
msg.retValue() << ",format=Protocol|Status";
for (ObjList* o = m_endpoints.skipNull(); o; o = o->skipNext()) {
YateH323EndPoint* ep = static_cast<YateH323EndPoint*>(o->get());
str.append(ep->c_str(),",") << "=H323|";
str << (ep->IsRegisteredWithGatekeeper() ? "registered" : "not-registered");
}
msg.retValue().append(str,";");
msg.retValue() << "\r\n";
return;
}
}
Driver::msgStatus(msg);
}
}; // anonymous namespace
/* vi: set ts=8 sw=4 sts=4 noet: */

View File

@ -41,10 +41,26 @@ class YMGCPEngine : public MGCPEngine
{
public:
inline YMGCPEngine(const NamedList* params)
: MGCPEngine(false,0,params)
: MGCPEngine(false,0,params), m_timedOutTrans(0), m_timedOutDels(0)
{ }
virtual ~YMGCPEngine();
virtual bool processEvent(MGCPTransaction* trans, MGCPMessage* msg, void* data);
virtual void timeout(MGCPTransaction* trans);
inline unsigned int trTimeouts()
{
unsigned int tmp = m_timedOutTrans;
m_timedOutTrans = 0;
return tmp;
}
inline unsigned int delTimeouts()
{
unsigned int tmp = m_timedOutDels;
m_timedOutDels = 0;
return tmp;
}
private:
unsigned int m_timedOutTrans;
unsigned int m_timedOutDels;
};
class MGCPWrapper : public DataEndpoint
@ -270,8 +286,11 @@ public:
virtual void statusDetail(String& str);
inline SDPParser& parser()
{ return m_parser; }
virtual void genUpdate(Message& msg);
virtual void appendNotif(NamedString* notif);
private:
SDPParser m_parser;
NamedList m_notifs;
};
YSIGFACTORY2(MGCPSpan);
@ -488,6 +507,24 @@ bool YMGCPEngine::processEvent(MGCPTransaction* trans, MGCPMessage* msg, void* d
return false;
}
void YMGCPEngine::timeout(MGCPTransaction* tr)
{
DDebug(&splugin,DebugInfo,"Handle timed out transaction [%p]",tr);
if (!tr)
return;
if (tr->timeout()) {
const MGCPMessage* cmd = tr->initial();
if (!cmd || !cmd->isCommand())
return;
if (cmd->name() != "DLCX")
m_timedOutTrans++;
else
m_timedOutDels++;
MGCPEndpointId epId(tr->ep());
splugin.appendNotif(new NamedString("mgcp_gw_down",epId.host()));
splugin.changed();
}
}
MGCPWrapper::MGCPWrapper(CallEndpoint* conn, const char* media, Message& msg, const char* epId)
: DataEndpoint(conn,media),
@ -1830,7 +1867,8 @@ bool DTMFHandler::received(Message& msg)
MGCPPlugin::MGCPPlugin()
: Module("mgcpca","misc",true),
m_parser("mgcpca","PSTN Circuit")
m_parser("mgcpca","PSTN Circuit"),
m_notifs("notifs")
{
Output("Loaded module MGCP-CA");
m_parser.debugChain(this);
@ -1944,6 +1982,21 @@ void MGCPPlugin::initialize()
m_parser.initialize(cfg.getSection("codecs"),cfg.getSection("hacks"));
}
void MGCPPlugin::genUpdate(Message& msg)
{
Lock l(this);
msg.copyParams(m_notifs);
msg.setParam("tr_timedout",String(s_engine->trTimeouts()));
msg.setParam("del_timedout",String(s_engine->delTimeouts()));
m_notifs.clearParams();
}
void MGCPPlugin::appendNotif(NamedString* notif)
{
Lock l(this);
m_notifs.addParam(notif);
}
}; // anonymous namespace
/* vi: set ts=8 sw=4 sts=4 noet: */

File diff suppressed because it is too large Load Diff

View File

@ -53,6 +53,7 @@ class MySqlConn;
class MyAcct;
static ObjList s_conns;
static unsigned int s_failedConns;
Mutex s_acctMutex(false,"MySQL::accts");
/**
@ -110,6 +111,23 @@ public:
void appendQuery(DbQuery* query);
void incTotal();
void incFailed();
void incErrorred();
void incQueryTime(u_int64_t with);
void lostConn();
void resetConn();
inline unsigned int total()
{ return m_totalQueries; }
inline unsigned int failed()
{ return m_failedQueries; }
inline unsigned int errorred()
{ return m_errorQueries; }
inline bool hasConn()
{ return ((int)(m_poolSize - m_failedConns) > 0 ? true : false); }
inline unsigned int queryTime()
{ return (unsigned int) m_queryTime; } //microseconds
private:
unsigned int m_timeout;
@ -128,6 +146,14 @@ private:
Semaphore m_queueSem;
Mutex m_queueMutex;
// stats counters
unsigned int m_totalQueries;
unsigned int m_failedQueries;
unsigned int m_errorQueries;
u_int64_t m_queryTime;
unsigned int m_failedConns;
Mutex m_incMutex;
};
/**
@ -168,9 +194,12 @@ class MyModule : public Module
public:
MyModule();
~MyModule();
void statusModule(String& str);
protected:
virtual void initialize();
virtual void statusParams(String& str);
virtual void statusDetail(String& str);
virtual void genUpdate(Message& msg);
private:
bool m_init;
};
@ -229,7 +258,7 @@ void MyConn::closeConn()
MYSQL* tmp = m_conn;
m_conn = 0;
mysql_close(tmp);
if(m_owner)
if (m_owner)
m_owner->m_connections.remove(this);
Debug(&module,DebugInfo,"Database connection '%s' closed",c_str());
}
@ -244,6 +273,7 @@ void MyConn::runQueries()
DbQuery* query = static_cast<DbQuery*>(m_owner->m_queryQueue.remove(false));
if (!query)
continue;
m_owner->incTotal();
mylock.drop();
DDebug(&module,DebugAll,"Connection '%s' will try to execute '%s'",
@ -268,11 +298,19 @@ bool MyConn::testDb()
// return number of rows, -1 for error
int MyConn::queryDbInternal(DbQuery* query)
{
if (!testDb())
if (!testDb()) {
m_owner->lostConn();
m_owner->incFailed();
return -1;
}
m_owner->resetConn();
u_int64_t start = Time::now();
if (mysql_real_query(m_conn,query->safe(),query->length())) {
Debug(&module,DebugWarn,"Query for '%s' failed: %s",c_str(),mysql_error(m_conn));
u_int64_t duration = Time::now() - start;
m_owner->incQueryTime(duration);
m_owner->incErrorred();
return -1;
}
@ -332,6 +370,9 @@ int MyConn::queryDbInternal(DbQuery* query)
}
} while (!mysql_next_result(m_conn));
u_int64_t finish = Time::now();
m_owner->incQueryTime(finish - start);
if (query->m_msg) {
query->m_msg->setParam("affected",String(affected));
if (warns)
@ -347,7 +388,10 @@ MyAcct::MyAcct(const NamedList* sect)
: String(*sect),
Mutex(true,"MySQL::acct"),
m_queueSem(MAX_CONNECTIONS,"MySQL::queue"),
m_queueMutex(false,"MySQL::queue")
m_queueMutex(false,"MySQL::queue"),
m_totalQueries(0), m_failedQueries(0), m_errorQueries(0),
m_queryTime(0), m_failedConns(0),
m_incMutex(false,"MySQL::inc")
{
int tout = sect->getIntValue("timeout",10000);
// round to seconds
@ -487,6 +531,60 @@ void MyAcct::dropDb()
s_libMutex.unlock();
}
void MyAcct::incTotal()
{
XDebug(&module,DebugAll,"MyAcct::incTotal() [%p] - currently there have been %d queries",this,m_totalQueries);
m_incMutex.lock();
m_totalQueries++;
m_incMutex.unlock();
module.changed();
}
void MyAcct::incFailed()
{
XDebug(&module,DebugAll,"MyAcct::incfailed() [%p] - currently there have been %d failed queries",this,m_failedQueries);
m_incMutex.lock();
m_failedQueries++;
m_incMutex.unlock();
module.changed();
}
void MyAcct::incErrorred()
{
XDebug(&module,DebugAll,"MyAcct::incErrorred() [%p] - currently there have been %d errorred queries",this,m_errorQueries);
m_incMutex.lock();
m_errorQueries++;
m_incMutex.unlock();
module.changed();
}
void MyAcct::incQueryTime(u_int64_t with)
{
XDebug(&module,DebugAll,"MyAcct::incQueryTime(with=" FMT64 ") [%p]",with,this);
m_incMutex.lock();
m_queryTime += with;
m_incMutex.unlock();
module.changed();
}
void MyAcct::lostConn()
{
DDebug(&module,DebugAll,"MyAcct::lostConn() [%p]",this);
m_incMutex.lock();
if (m_failedConns < (unsigned int) m_poolSize)
m_failedConns++;
m_incMutex.unlock();
module.changed();
}
void MyAcct::resetConn()
{
DDebug(&module,DebugAll,"MyAcct::hasConn() [%p]",this);
m_incMutex.lock();
m_failedConns = 0;
m_incMutex.unlock();
}
void MyAcct::appendQuery(DbQuery* query)
{
DDebug(&module, DebugAll, "Account '%s' received a new query %p",c_str(),query);
@ -574,11 +672,31 @@ MyModule::~MyModule()
{
Output("Unloading module MySQL");
s_conns.clear();
s_failedConns = 0;
}
void MyModule::statusModule(String& str)
{
Module::statusModule(str);
str.append("format=Total|Failed|Errors|AvgExecTime",",");
}
void MyModule::statusParams(String& str)
{
str.append("conns=",",") << s_conns.count();
str.append("failed=",",") << s_failedConns;
}
void MyModule::statusDetail(String& str)
{
for (unsigned int i = 0; i < s_conns.count(); i++) {
MyAcct* acc = static_cast<MyAcct*>(s_conns[i]);
str.append(acc->c_str(),",") << "=" << acc->total() << "|" << acc->failed() << "|" << acc->errorred() << "|";
if (acc->total() - acc->failed() > 0)
str << (acc->queryTime() / (acc->total() - acc->failed()) / 1000); //miliseconds
else
str << "0";
}
}
void MyModule::initialize()
@ -589,6 +707,7 @@ void MyModule::initialize()
if (m_init)
Engine::install(new MyHandler(cfg.getIntValue("general","priority",100)));
m_init = false;
s_failedConns = 0;
for (unsigned int i = 0; i < cfg.sections(); i++) {
NamedList* sec = cfg.getSection(i);
if (!sec || (*sec == "general"))
@ -604,11 +723,36 @@ void MyModule::initialize()
conn = new MyAcct(sec);
s_conns.insert(conn);
if (!conn->initDb())
if (!conn->initDb()) {
s_conns.remove(conn);
s_failedConns++;
}
}
}
void MyModule::genUpdate(Message& msg)
{
Lock lock(this);
unsigned int index = 0;
String db = "database.";
String total = "total.";
String failed = "failed.";
String error = "errorred.";
String conn = "hasconn.";
String time = "querytime.";
for (ObjList* o = s_conns.skipNull(); o; o = o->next()) {
MyAcct* acc = static_cast<MyAcct*>(o->get());
msg.setParam(db << index,acc->toString());
msg.setParam(total << index,String(acc->total()));
msg.setParam(failed << index,String(acc->failed()));
msg.setParam(error << index,String(acc->errorred()));
msg.setParam(conn << index,String::boolText(acc->hasConn()));
msg.setParam(time << index,String(acc->queryTime()));
index++;
}
msg.setParam("count",String(index));
}
}; // anonymous namespace
/* vi: set ts=8 sw=4 sts=4 noet: */

View File

@ -32,6 +32,7 @@ namespace { // anonymous
static ObjList s_conns;
Mutex s_conmutex(false,"PgSQL::conn");
static unsigned int s_failedConns;
class PgConn : public RefObject, public Mutex
{
@ -46,6 +47,19 @@ public:
int queryDb(const char* query, Message* dest = 0);
bool initDb(int retry = 0);
inline unsigned int total()
{ return m_totalQueries; }
inline unsigned int failed()
{ return m_failedQueries; }
inline unsigned int errorred()
{ return m_errorQueries; }
inline unsigned int queryTime()
{ return (unsigned int) m_queryTime; }
inline void setConn(bool conn = true)
{ m_hasConn = conn; }
inline bool hasConn()
{ return m_hasConn; }
private:
void dropDb();
bool testDb();
@ -56,6 +70,13 @@ private:
int m_retry;
u_int64_t m_timeout;
PGconn *m_conn;
// stat counters
unsigned int m_totalQueries;
unsigned int m_failedQueries;
unsigned int m_errorQueries;
u_int64_t m_queryTime;
bool m_hasConn;
};
class PgHandler : public MessageHandler
@ -74,7 +95,10 @@ public:
~PgModule();
protected:
virtual void initialize();
virtual void statusModule(String& str);
virtual void statusParams(String& str);
virtual void statusDetail(String& str);
virtual void genUpdate(Message& msg);
private:
bool m_init;
};
@ -83,7 +107,9 @@ static PgModule module;
PgConn::PgConn(const NamedList* sect)
: Mutex(true,"PgConn"),
m_name(*sect), m_conn(0)
m_name(*sect), m_conn(0),
m_totalQueries(0), m_failedQueries(0),
m_errorQueries(0), m_queryTime(0), m_hasConn(false)
{
m_connection = sect->getValue("connection");
if (m_connection.null()) {
@ -204,6 +230,7 @@ bool PgConn::ok()
// try to get up the connection, retry if we have to
bool PgConn::startDb()
{
setConn(true);
if (testDb())
return true;
for (int i = 0; i < m_retry; i++) {
@ -213,6 +240,7 @@ bool PgConn::startDb()
if (testDb())
return true;
}
setConn(false);
return false;
}
@ -313,6 +341,8 @@ int PgConn::queryDbInternal(const char* query, Message* dest)
default:
Debug(&module,DebugWarn,"Query error: %s",PQresultErrorMessage(res));
dest->setParam("error",PQresultErrorMessage(res));
m_errorQueries++;
module.changed();
}
PQclear(res);
}
@ -335,12 +365,21 @@ int PgConn::queryDb(const char* query, Message* dest)
return -1;
Debug(&module,DebugAll,"Performing query \"%s\" for '%s'",
query,m_name.c_str());
m_totalQueries++;
module.changed();
u_int64_t start = Time::now();
for (int i = 0; i < m_retry; i++) {
int res = queryDbInternal(query,dest);
if (res > -2) {
if (res < 0)
if (res < 0) {
failure(dest);
m_failedQueries++;
module.changed();
}
// ok or non-retryable error, get out of here
u_int64_t finish = Time::now() - start;
m_queryTime += finish;
module.changed();
return res;
}
}
@ -348,7 +387,6 @@ int PgConn::queryDb(const char* query, Message* dest)
return -2;
}
static PgConn* findDb(const String& account)
{
if (account.null())
@ -385,10 +423,32 @@ PgModule::~PgModule()
s_conns.clear();
}
void PgModule::statusModule(String& str)
{
Module::statusModule(str);
str.append("format=Total|Failed|Errors|AvgExecTime",",");
}
void PgModule::statusParams(String& str)
{
s_conmutex.lock();
str.append("conns=",",") << s_conns.count();
str.append("failed=",",") << s_failedConns;
s_conmutex.unlock();
}
void PgModule::statusDetail(String& str)
{
s_conmutex.lock();
for (unsigned int i = 0; i < s_conns.count(); i++) {
PgConn* conn = static_cast<PgConn*>(s_conns[i]);
str.append(conn->toString().c_str(),",") << "=" << conn->total() << "|" << conn->failed()
<< "|" << conn->errorred() << "|";
if (conn->total() - conn->failed() > 0)
str << (conn->queryTime() / (conn->total() - conn->failed()) / 1000); //miliseconds
else
str << "0";
}
s_conmutex.unlock();
}
@ -410,12 +470,36 @@ void PgModule::initialize()
if (sec->getBoolValue("autostart",true))
conn->initDb();
s_conmutex.lock();
s_conns.insert(conn);
if (conn->ok())
s_conns.insert(conn);
else
s_failedConns++;
s_conmutex.unlock();
}
}
void PgModule::genUpdate(Message& msg)
{
unsigned int index = 0;
String db = "database.";
String total = "total.";
String failed = "failed.";
String error = "errorred.";
String hasconn = "hasconn.";
String time = "querytime.";
for (ObjList* o = s_conns.skipNull(); o; o = o->next()) {
PgConn* conn = static_cast<PgConn*>(o->get());
msg.setParam(db << index,conn->toString());
msg.setParam(total << index,String(conn->total()));
msg.setParam(failed << index,String(conn->failed()));
msg.setParam(error << index,String(conn->errorred()));
msg.setParam(hasconn << index,String::boolText(conn->hasConn()));
msg.setParam(time << index,String(conn->queryTime()));
index++;
}
msg.setParam("count",String(index));
}
}; // anonymous namespace
/* vi: set ts=8 sw=4 sts=4 noet: */

View File

@ -200,6 +200,7 @@ private:
u_int64_t m_sent;
u_int64_t m_received;
struct timeval m_tv;
bool m_down;
};
class TdmInterface : public SignallingInterface, public TdmWorker
@ -456,6 +457,25 @@ static inline bool getBoolValue(const char* param, const NamedList& config,
}
static void sendModuleUpdate(const String& notif, const String& device, bool& notifStat, int status = 0)
{
Message* msg = new Message("module.update");
msg->addParam("module",plugin.name());
msg->addParam("interface",device);
msg->addParam("notify",notif);
if(notifStat && status == SignallingInterface::LinkUp) {
notifStat = false;
Engine::enqueue(msg);
return;
}
if (!notifStat && status == SignallingInterface::LinkDown) {
notifStat = true;
Engine::enqueue(msg);
return;
}
TelEngine::destruct(msg);
}
bool TdmWorker::running() const
{
return m_thread && m_thread->running();
@ -556,6 +576,7 @@ TdmDevice::TdmDevice(Type t, SignallingComponent* dbg, unsigned int chan,
return;
}
m_sent = m_received = 0;
m_down = false;
plugin.append(this);
}
@ -1009,9 +1030,11 @@ bool TdmDevice::checkEvents()
case WP_TDMAPI_EVENT_ALARM:
if (!rx_event->wp_tdm_api_event_alarm) {
DDebug(m_owner,DebugWarn,"%s: Link is disconnected",tdmName().c_str());
sendModuleUpdate("interfaceDown",tdmName(),m_down,SignallingInterface::LinkDown);
}
else {
DDebug(m_owner,DebugInfo,"%s: Link is connected",tdmName().c_str());
sendModuleUpdate("interfaceUp",tdmName(),m_down,SignallingInterface::LinkUp);
}
decode_alarms(rx_event->wp_tdm_api_event_alarm);
break;
@ -1800,6 +1823,7 @@ bool TdmInterface::process()
return false;
if (!m_device.canRead())
return false;
m_device.checkEvents();
int r = m_device.receiveData(m_buffer,m_bufsize);
if (r <= 0)
return false;

View File

@ -263,6 +263,7 @@ private:
bool m_repeatCapable; // HW repeat available
Mutex m_repeatMutex; // Lock repeat buffer
DataBlock m_repeatPacket; // Packet to repeat
bool m_down;
};
// Read signalling data for WpInterface
@ -445,6 +446,26 @@ static bool s_repeatCapable = true; // Global repeat packet capability
static WpModule driver;
static void sendModuleUpdate(bool& notifStat, int status, const String& device)
{
Message* msg = new Message("module.update");
msg->addParam("module",driver.name());
msg->addParam("interface",device);
if(notifStat && status == SignallingInterface::LinkUp) {
msg->addParam("notify","interfaceUp");
notifStat = false;
Engine::enqueue(msg);
return;
}
if (!notifStat && status == SignallingInterface::LinkDown) {
msg->addParam("notify","interfaceDown");
notifStat = true;
Engine::enqueue(msg);
return;
}
TelEngine::destruct(msg);
}
/**
* Fifo
*/
@ -849,6 +870,7 @@ bool WpInterface::init(const NamedList& config, NamedList& params)
s << " hwrepeatcapable=" << String::boolText(m_repeatCapable);
Debug(this,DebugInfo,"D-channel: %s [%p]",s.c_str(),this);
}
m_down = false;
return true;
}
@ -1038,10 +1060,14 @@ bool WpInterface::updateStatus()
return false;
Debug(this,DebugNote,"Link status changed to %s [%p]",
lookup(m_socket.status(),s_linkStatus),this);
if (m_socket.status() == WpSocket::Connected)
if (m_socket.status() == WpSocket::Connected) {
notify(LinkUp);
else
sendModuleUpdate(m_down,LinkUp,m_socket.card());
}
else {
notify(LinkDown);
sendModuleUpdate(m_down,LinkDown,m_socket.card());
}
return true;
}

View File

@ -44,7 +44,7 @@ class SigIsdnCallRecord; // Record an ISDN call monitor
class SigTrunkThread; // Get events and check timeout for trunks that have a call controller
class IsupDecodeHandler; // Handler for "isup.decode" message
class IsupEncodeHandler; // Handler for "isup.encode" message
class SigNotifier; // Class for handling received notifications
// The signalling channel
class SigChannel : public Channel, public MessageNotifier
@ -247,6 +247,15 @@ class SigTopmost : public TopMost
{
public:
SigTopmost(const char* name);
// Return the status of this component
virtual inline void status(String& retVal)
{ }
// Return the status of a signalling interface
virtual inline void ifStatus(String& status)
{ }
// Return the status of a link
virtual inline void linkStatus(String& status)
{ }
protected:
virtual void destroyed();
};
@ -261,6 +270,10 @@ public:
// Initialize (create or reload) the linkset
// Return false on failure
virtual bool initialize(NamedList& params);
// Return the status of this component
virtual void status(String& retVal);
virtual void ifStatus(String& status);
virtual void linkStatus(String& status);
protected:
virtual void destroyed();
private:
@ -338,6 +351,10 @@ public:
void cleanup();
// Type names
static const TokenDict s_type[];
virtual inline void ifStatus(String& status)
{ }
virtual inline void linkStatus(String& status)
{ }
protected:
// Cancel thread. Cleanup. Remove from plugin list
virtual void destroyed();
@ -390,6 +407,8 @@ class SigIsdn : public SigTrunk
public:
SigIsdn(const char* name, Type type);
virtual ~SigIsdn();
virtual void ifStatus(String& status);
virtual void linkStatus(String& status);
protected:
virtual bool create(NamedList& params, String& error);
virtual bool reload(NamedList& params);
@ -618,8 +637,18 @@ public:
virtual bool received(Message& msg);
};
class SigNotifier : public SignallingNotifier
{
public:
inline ~SigNotifier()
{ }
virtual void notify(NamedList& params);
virtual void cleanup();
};
static SigDriver plugin;
static SigFactory factory;
static SigNotifier s_notifier;
static Configuration s_cfg;
static Configuration s_cfgData;
static const String s_noPrefixParams = "format,earlymedia";
@ -714,8 +743,11 @@ SignallingComponent* SigFactory::create(const String& type, const NamedList& nam
case SigISDNLayer2:
if (ty && *ty == "isdn-iua")
return new ISDNIUA(*config);
if (name.getBoolValue("primary",true))
return new ISDNQ921(*config,name);
if (name.getBoolValue("primary",true)) {
NamedList cfg(*config);
cfg.setParam("type",lookup(compType,s_compNames));
return new ISDNQ921(cfg,name);
}
return new ISDNQ921Management(*config,name,name.getBoolValue("network",true));
case SigISDNLayer3:
return new ISDNQ931(*config,name);
@ -1686,6 +1718,46 @@ bool SigDriver::received(Message& msg, int id)
if (!target.startSkip(name()))
return false;
if (target.startSkip("links")) {
msg.retValue() << "module=" << name();
msg.retValue() << ",format=Type|Status";
String ret = "";
m_trunksMutex.lock();
for (ObjList* o = m_trunks.skipNull(); o; o = o->skipNext()) {
SigTrunk* trunk = static_cast<SigTrunk*>(o->get());
trunk->linkStatus(ret);
}
m_trunksMutex.unlock();
m_topmostMutex.lock();
for (ObjList* o = m_topmost.skipNull(); o; o = o->skipNext()) {
SigTopmost* top = static_cast<SigTopmost*>(o->get());
top->linkStatus(ret);
}
m_topmostMutex.unlock();
if (!ret.null())
msg.retValue() << ";" << ret;
msg.retValue() << "\r\n";
}
if (target.startSkip("ifaces")) {
msg.retValue() << "module=" << name();
msg.retValue() << ",format=Status";
String ret = "";
m_trunksMutex.lock();
for (ObjList* o = m_trunks.skipNull(); o; o = o->skipNext()) {
SigTrunk* trunk = static_cast<SigTrunk*>(o->get());
trunk->ifStatus(ret);
}
m_trunksMutex.unlock();
m_topmostMutex.lock();
for (ObjList* o = m_topmost.skipNull(); o; o = o->skipNext()) {
SigTopmost* top = static_cast<SigTopmost*>(o->get());
top->ifStatus(ret);
}
m_topmostMutex.unlock();
if (!ret.null())
msg.retValue() << ";" << ret;
msg.retValue() << "\r\n";
}
// Status target=trunk[/cic|/range]
int pos = target.find("/");
@ -1762,6 +1834,10 @@ void SigDriver::status(SigTopmost* topmost, String& retVal)
retVal.clear();
retVal << "module=" << name();
retVal << ",component=" << topmost->name();
String details = "";
topmost->status(details);
if (!details.null())
retVal << "," << details;
retVal << "\r\n";
}
@ -1984,6 +2060,8 @@ bool SigDriver::commandComplete(Message& msg, const String& partLine,
Lock lock(this);
// line='status sig': add trunks and topmost components
if (partLine == m_statusCmd) {
itemComplete(msg.retValue(),"links",partWord);
itemComplete(msg.retValue(),"ifaces",partWord);
ObjList* o;
m_trunksMutex.lock();
for (o = m_trunks.skipNull(); o; o = o->skipNext())
@ -2338,6 +2416,7 @@ void SigDriver::initialize()
m_engine = SignallingEngine::self(true);
m_engine->debugChain(this);
m_engine->start();
m_engine->setNotifier(&s_notifier);
}
// Apply debug levels to driver and engine
int level = s_cfg.getIntValue("general","debuglevel",-1);
@ -2413,6 +2492,54 @@ bool SigLinkSet::initialize(NamedList& params)
return m_linkset && m_linkset->initialize(&params);
}
void SigLinkSet::status(String& retVal)
{
retVal << "type=" << (m_linkset ? m_linkset->componentType() : "");
retVal << ",status=" << (m_linkset && m_linkset->operational() ? "" : "non-") << "operational";
}
void SigLinkSet::ifStatus(String& status)
{
SS7MTP3* mtp3 = static_cast<SS7MTP3*>(m_linkset);
if (mtp3) {
const ObjList* list = mtp3->links();
for (ObjList* o = list->skipNull(); o; o = o->skipNext()) {
GenPointer<SS7Layer2>* p = static_cast<GenPointer<SS7Layer2>*>(o->get());
if (!*p)
continue;
SS7Layer2* link = *p;
SS7MTP2* mtp2 = static_cast<SS7MTP2*>(link->getObject("SS7MTP2"));
if (mtp2) {
SignallingInterface* sigIface = mtp2->iface();
if (sigIface) {
status.append(sigIface->toString(),",");
status << "=" << (sigIface->control(SignallingInterface::Query) ? "" : "non-");
status << "operational";
}
}
}
}
}
void SigLinkSet::linkStatus(String& status)
{
SS7MTP3* mtp3 = static_cast<SS7MTP3*>(m_linkset);
if (mtp3) {
const ObjList* list = mtp3->links();
for (ObjList* o = list->skipNull(); o; o = o->skipNext()) {
GenPointer<SS7Layer2>* p = static_cast<GenPointer<SS7Layer2>*>(o->get());
if (!*p)
continue;
SS7Layer2* link = *p;
if (link) {
status.append(link->toString(),",") << "=";
status << link->componentType() ;
status << "|" << link->statusName();
}
}
}
}
/**
* SigTesting
@ -2871,6 +2998,31 @@ void SigIsdn::release()
XDebug(&plugin,DebugAll,"SigIsdn('%s'). Released [%p]",name().c_str(),this);
}
void SigIsdn::ifStatus(String& status)
{
if (m_controller) {
const ISDNQ921* l2 = static_cast<const ISDNQ921*>(q931()->layer2());
if (l2) {
SignallingInterface* sigIface = l2->iface();
if (sigIface) {
status.append(sigIface->toString(),",");
status << "=" << (sigIface->control(SignallingInterface::Query) ? "" : "non-") << "operational";
}
}
}
}
void SigIsdn::linkStatus(String& status)
{
if (m_controller) {
const ISDNLayer2* l2 = static_cast<const ISDNLayer2*>(q931()->layer2());
if (l2) {
status.append(l2->toString(),",") << "=";
status << l2->componentType();
status << "|" << l2->stateName(l2->state());
}
}
}
/**
* SigIsdnMonitor
@ -3689,6 +3841,26 @@ bool IsupEncodeHandler::received(Message& msg)
return false;
}
/**
* SigNotifier
*/
void SigNotifier::notify(NamedList& notifs)
{
Debug(&plugin,DebugInfo,"SigNotifier [%p] received a notify ",this);
Message* msg = new Message("module.update");
msg->addParam("module",plugin.name());
msg->copyParams(notifs);
Engine::enqueue(msg);
}
void SigNotifier::cleanup()
{
DDebug(&plugin,DebugInfo,"SigNotifier [%p] cleanup()",this);
SignallingEngine* engine = plugin.engine();
if (engine)
engine->removeNotifier(this);
}
}; // anonymous namespace
/* vi: set ts=8 sw=4 sts=4 noet: */

File diff suppressed because it is too large Load Diff

View File

@ -555,6 +555,7 @@ private:
bool m_sendReadOnly; // Print send attempt on readonly interface error
int m_notify; // Notify receiver on channel non idle (0: success. 1: not notified. 2: notified)
SignallingTimer m_timerRxUnder; // RX underrun notification
bool m_down; // Interface status
};
// Signalling span used to create voice circuits
@ -775,6 +776,32 @@ static inline bool getBoolValue(const char* param, const NamedList& config,
return params.getBoolValue(param,defVal);
}
static void sendModuleUpdate(const String& notif, const String& device, bool& notifStat, int status = 0)
{
Message* msg = new Message("module.update");
msg->addParam("module",plugin.name());
msg->addParam("interface",device);
msg->addParam("notify",notif);
if(notifStat && status == SignallingInterface::LinkUp) {
notifStat = false;
Engine::enqueue(msg);
return;
}
if (!notifStat && status == SignallingInterface::LinkDown) {
notifStat = true;
Engine::enqueue(msg);
return;
}
if (notif == "alarm") {
if (status == ZapDevice::Yellow)
msg->addParam("notify","RAI");
if (status == ZapDevice::Blue)
msg->addParam("notify","AIS");
Engine::enqueue(msg);
return;
}
TelEngine::destruct(msg);
}
/**
* ZapWorkerClient
@ -1363,8 +1390,13 @@ bool ZapDevice::checkAlarms()
m_alarmsText = "";
if (m_alarms) {
for(int i = 0; s_alarms[i].token; i++)
if (m_alarms & s_alarms[i].value)
if (m_alarms & s_alarms[i].value) {
m_alarmsText.append(s_alarms[i].token,",");
if (s_alarms[i].value == ZapDevice::Yellow || s_alarms[i].value == ZapDevice::Blue) {
bool notifStat = false;
sendModuleUpdate("alarm",zapName(),notifStat,s_alarms[i].value);
}
}
Debug(m_owner,DebugNote,"%sAlarms changed (%d,'%s') on channel %u [%p]",
m_name.safe(),m_alarms,m_alarmsText.safe(),m_channel,m_owner);
}
@ -1788,6 +1820,7 @@ bool ZapInterface::init(ZapDevice::Type type, unsigned int code, unsigned int ch
s << " priority=" << Thread::priority(m_priority);
Debug(this,DebugInfo,"D-channel: %s [%p]",s.c_str(),this);
}
m_down = false;
return true;
}
@ -1941,11 +1974,13 @@ void ZapInterface::checkEvents()
Debug(this,DebugNote,"Alarms changed '%s' [%p]",
m_device.alarmsText().safe(),this);
notify(LinkDown);
sendModuleUpdate("interfaceDown",m_device.zapName(),m_down,LinkDown);
}
else {
m_device.resetAlarms();
DDebug(this,DebugInfo,"No more alarms [%p]",this);
notify(LinkUp);
sendModuleUpdate("interfaceUp",m_device.zapName(),m_down,LinkUp);
}
return;
case ZapDevice::HdlcAbort:

View File

@ -182,6 +182,12 @@ public:
inline bool hasLine(const String& line)
{ Lock lock(this); return findLine(line) != 0; }
/**
* Get a copy of the lines list
*/
inline ObjList* lines()
{ Lock lock(this); return m_lines.skipNull();}
protected:
bool updateLine(YIAXLine* line, Message &msg);
bool addLine(Message &msg);
@ -384,6 +390,9 @@ public:
bool userAuth(IAXTransaction* tr, bool response, bool& requestAuth,
bool& invalidAuth);
bool commandComplete(Message& msg, const String& partLine, const String& partWord);
void msgStatus(Message& msg);
protected:
YIAXEngine* m_iaxEngine;
u_int32_t m_defaultCodec;
@ -528,6 +537,7 @@ static YIAXLineContainer s_lines; // Lines
static Thread::Priority s_priority = Thread::Normal; // Threads priority
static YIAXDriver iplugin; // Init the driver
static String s_statusCmd = "status";
/*
* Class definitions
@ -1151,6 +1161,7 @@ void YIAXDriver::initialize()
installRelay(Halt);
installRelay(Route);
installRelay(Progress);
installRelay(Status);
Engine::install(new YIAXRegDataHandler);
// Init IAX engine
u_int16_t transListCount = 64;
@ -1261,6 +1272,12 @@ bool YIAXDriver::received(Message& msg, int id)
channels().clear();
s_lines.clear();
}
else
if (id == Status) {
String target = msg.getValue("module");
if (target && target.startsWith(name()) && !target.startsWith(prefix()))
msgStatus(msg);
}
return Driver::received(msg,id);
}
@ -1343,6 +1360,41 @@ bool YIAXDriver::userAuth(IAXTransaction* tr, bool response, bool& requestAuth,
return true;
}
bool YIAXDriver::commandComplete(Message& msg, const String& partLine, const String& partWord)
{
String cmd = s_statusCmd;
cmd << " " << name();
if (partLine == cmd)
itemComplete(msg.retValue(),"accounts",partWord);
else
return Driver::commandComplete(msg,partLine,partWord);
return false;
}
void YIAXDriver::msgStatus(Message& msg)
{
String str = msg.getValue("module");
while (str.startSkip(name())) {
str.trimBlanks();
if (str.null())
break;
if (str.startSkip("accounts")) {
msg.retValue().clear();
msg.retValue() << "module=" << name();
msg.retValue() << ",format=Protocol|Status";
for (ObjList* o = s_lines.lines(); o; o = o->skipNext()) {
YIAXLine* line = static_cast<YIAXLine*>(o->get());
str.append(line->username(),",") << "=IAX|";
str << (line-> registered() ? "online" : "offline");
}
msg.retValue().append(str,";");
msg.retValue() << "\r\n";
return;
}
}
Driver::msgStatus(msg);
}
/**
* IAXConsumer
*/

View File

@ -188,6 +188,9 @@ private:
unsigned int m_port;
bool m_audio;
bool m_valid;
unsigned int m_noAudio;
unsigned int m_lostAudio;
};
class YRTPSession : public RTPSession
@ -366,6 +369,10 @@ public:
virtual bool received(Message& msg, int id);
virtual void statusParams(String& str);
virtual void statusDetail(String& str);
void addStats(const NamedList& stats);
void genUpdate(Message& msg);
private:
bool reflectSetup(Message& msg, const char* id, RTPTransport& rtp, const char* rHost, const char* leg);
bool reflectStart(Message& msg, const char* id, RTPTransport& rtp, SocketAddr& rAddr);
@ -374,6 +381,7 @@ private:
void reflectAnswer(Message& msg, bool ignore);
void reflectHangup(Message& msg);
bool m_first;
ObjList m_updates;
};
static YRTPPlugin splugin;
@ -387,7 +395,7 @@ static Mutex s_srcMutex(false,"YRTPChan::source");
YRTPWrapper::YRTPWrapper(const char* localip, CallEndpoint* conn, const char* media, RTPSession::Direction direction, Message& msg, bool udptl)
: m_rtp(0), m_udptl(0), m_dir(direction), m_conn(conn),
m_source(0), m_consumer(0), m_media(media),
m_bufsize(0), m_port(0), m_valid(true)
m_bufsize(0), m_port(0), m_valid(true), m_noAudio(0), m_lostAudio(0)
{
Debug(&splugin,DebugAll,"YRTPWrapper::YRTPWrapper('%s',%p,'%s',%s,%p,%s) [%p]",
localip,conn,media,lookup(direction,dict_yrtp_dir),
@ -825,6 +833,10 @@ void YRTPWrapper::timeout(bool initial)
{
if (!(initial ? s_warnFirst : s_warnLater))
return;
if (initial)
m_noAudio++;
else
m_lostAudio++;
Debug(&splugin,DebugWarn,"%s timeout in%s%s wrapper [%p]",
(initial ? "Initial" : "Later"),
(m_master ? " channel " : ""),
@ -885,8 +897,15 @@ void YRTPWrapper::terminate(Message& msg)
{
Debug(&splugin,DebugInfo,"YRTPWrapper::terminate() [%p]",this);
String stats;
if (m_rtp)
if (m_rtp) {
NamedList nl("");
m_rtp->getStats(nl);
nl.setParam("noaudio",String(m_noAudio));
nl.setParam("lostaudio",String(m_lostAudio));
splugin.addStats(nl);
splugin.changed();
m_rtp->getStats(stats);
}
if (m_udptl)
m_udptl->getStats(stats);
if (stats)
@ -1461,6 +1480,25 @@ YRTPPlugin::~YRTPPlugin()
s_mirrors.clear();
}
void YRTPPlugin::addStats(const NamedList& stats)
{
DDebug(this,DebugAll,"Add updates");
s_mutex.lock();
m_updates.append(new NamedList(stats));
s_mutex.unlock();
}
void YRTPPlugin::genUpdate(Message& msg)
{
DDebug(this,DebugAll,"::genUpdate() [%p] updates=%d",this,m_updates.count());
Lock l(s_mutex);
if (m_updates.count() == 0)
return;
NamedList* updateParams = static_cast<NamedList*>(m_updates.remove(false));
msg.copyParams(*updateParams);
TelEngine::destruct(updateParams);
}
void YRTPPlugin::statusParams(String& str)
{
s_mutex.lock();

View File

@ -199,6 +199,26 @@ public:
{ return m_port; }
inline Socket* socket() const
{ return m_sock; }
inline void incFailedAuths()
{ m_failedAuths++; }
inline unsigned int failedAuths()
{
unsigned int tmp = m_failedAuths;
m_failedAuths = 0;
return tmp;
}
inline unsigned int timedOutTrs()
{
unsigned int tmp = m_timedOutTrs;
m_timedOutTrs = 0;
return tmp;
}
inline unsigned int timedOutByes()
{
unsigned int tmp = m_timedOutByes;
m_timedOutByes = 0;
return tmp;
}
private:
void addMessage(const char* buf, int len, const SocketAddr& addr, int port);
int m_port;
@ -207,6 +227,10 @@ private:
SocketAddr m_addr;
YateSIPEngine *m_engine;
DataBlock m_buffer;
unsigned int m_failedAuths;
unsigned int m_timedOutTrs;
unsigned int m_timedOutByes;
};
// Handle transfer requests
@ -460,6 +484,10 @@ public:
YateSIPLine* findLine(const String& line) const;
YateSIPLine* findLine(const String& addr, int port, const String& user = String::empty());
bool validLine(const String& line);
bool commandComplete(Message& msg, const String& partLine, const String& partWord);
void msgStatus(Message& msg);
protected:
virtual void genUpdate(Message& msg);
private:
SDPParser m_parser;
YateSIPEndPoint *m_endpoint;
@ -491,6 +519,8 @@ static int s_expires_min = EXPIRES_MIN;
static int s_expires_def = EXPIRES_DEF;
static int s_expires_max = EXPIRES_MAX;
static String s_statusCmd = "status";
// Check if an IPv4 address belongs to one of the non-routable blocks
static bool isPrivateAddr(const String& host)
{
@ -988,15 +1018,24 @@ bool YateSIPEngine::checkUser(const String& username, const String& realm, const
return copyAuthParams(params,m);
// if the URI included some parameters retry after stripping them off
int sc = uri.find(';');
if (sc < 0)
return false;
buildAuth(username,realm,m.retValue(),nonce,method,uri.substr(0,sc),res);
return (res == response) && copyAuthParams(params,m);
bool ok = false;
if (sc >= 0) {
buildAuth(username,realm,m.retValue(),nonce,method,uri.substr(0,sc),res);
ok = (res == response) && copyAuthParams(params,m);
}
if (!ok && !response.null()) {
DDebug(&plugin,DebugNote,"Failed authentication for username='%s'",username.c_str());
m_ep->incFailedAuths();
plugin.changed();
}
return ok;
}
YateSIPEndPoint::YateSIPEndPoint(Thread::Priority prio)
: Thread("YSIP EndPoint",prio),
m_sock(0), m_engine(0)
m_sock(0), m_engine(0),
m_failedAuths(0),m_timedOutTrs(0), m_timedOutByes(0)
{
Debug(&plugin,DebugAll,"YateSIPEndPoint::YateSIPEndPoint(%s) [%p]",
Thread::priority(prio),this);
@ -1215,10 +1254,25 @@ void YateSIPEndPoint::run()
evCount = 0;
// hack: use a loop so we can use break and continue
for (; e; m_engine->processEvent(e),e = 0) {
if (!e->getTransaction())
SIPTransaction* t = e->getTransaction();
if (!t)
continue;
plugin.lock();
GenObject* obj = static_cast<GenObject*>(e->getTransaction()->getUserData());
if (t->isOutgoing() && t->getResponseCode() == 408) {
if (t->getMethod() == "BYE") {
DDebug(&plugin,DebugInfo,"BYE for transaction %p has timed out",t);
m_timedOutByes++;
plugin.changed();
}
if (e->getState() == SIPTransaction::Cleared && e->getUserData()) {
DDebug(&plugin,DebugInfo,"Transaction %p has timed out",t);
m_timedOutTrs++;
plugin.changed();
}
}
GenObject* obj = static_cast<GenObject*>(t->getUserData());
RefPointer<YateSIPConnection> conn = YOBJECT(YateSIPConnection,obj);
YateSIPLine* line = YOBJECT(YateSIPLine,obj);
YateSIPGenerate* gen = YOBJECT(YateSIPGenerate,obj);
@ -4117,6 +4171,13 @@ bool SIPDriver::received(Message& msg, int id)
channels().clear();
s_lines.clear();
}
else if (id == Status) {
String target = msg.getValue("module");
if (target && target.startsWith(name()) && !target.startsWith(prefix())) {
msgStatus(msg);
return true;
}
}
return Driver::received(msg,id);
}
@ -4206,12 +4267,59 @@ void SIPDriver::initialize()
installRelay(Progress);
installRelay(Update);
installRelay(Route);
installRelay(Status);
Engine::install(new UserHandler);
if (s_cfg.getBoolValue("general","generate"))
Engine::install(new SipHandler);
}
}
void SIPDriver::genUpdate(Message& msg)
{
DDebug(this,DebugInfo,"fill module.update message");
Lock l(this);
if (m_endpoint) {
msg.setParam("failed_auths",String(m_endpoint->failedAuths()));
msg.setParam("transaction_timeouts",String(m_endpoint->timedOutTrs()));
msg.setParam("bye_timeouts",String(m_endpoint->timedOutByes()));
}
}
bool SIPDriver::commandComplete(Message& msg, const String& partLine, const String& partWord)
{
String cmd = s_statusCmd;
cmd << " " << name();
if (partLine == cmd)
itemComplete(msg.retValue(),"accounts",partWord);
else
return Driver::commandComplete(msg,partLine,partWord);
return false;
}
void SIPDriver::msgStatus(Message& msg)
{
String str = msg.getValue("module");
while (str.startSkip(name())) {
str.trimBlanks();
if (str.null())
Module::msgStatus(msg);
else if (str.startSkip("accounts")) {
msg.retValue().clear();
msg.retValue() << "module=" << name();
msg.retValue() << ",format=Protocol|Status";
String accounts = "";
for (ObjList* o = s_lines.skipNull(); o; o = o->skipNext()) {
YateSIPLine* line = static_cast<YateSIPLine*>(o->get());
accounts.append(line->getUserName(),",") << "=SIP|";
accounts << (line->valid() ? "online" : "offline");
}
msg.retValue().append(accounts,";");
msg.retValue() << "\r\n";
return;
}
}
}
}; // anonymous namespace
/* vi: set ts=8 sw=4 sts=4 noet: */

View File

@ -86,6 +86,8 @@ for small to large scale projects.
%{_bindir}/yate
%{_mandir}/*/yate.*
%{_initrddir}/yate
%dir %{_datadir}/yate/data
%{_datadir}/yate/data/*
%dir %{_libdir}/yate
%{_libdir}/yate/cdrbuild.yate
%{_libdir}/yate/cdrfile.yate
@ -140,6 +142,8 @@ for small to large scale projects.
%{_libdir}/yate/server/users.yate
%{_libdir}/yate/server/presence.yate
%{_libdir}/yate/server/subscription.yate
%{_libdir}/yate/server/monitoring.yate
%{_libdir}/yate/server/ysnmpagent.yate
%{_libdir}/yate/client/osschan.yate
%{_libdir}/yate/client/jabberclient.yate
%{_libdir}/yate/jabber/jabberserver.yate
@ -182,6 +186,11 @@ for small to large scale projects.
%config(noreplace) %{_sysconfdir}/yate/ciscosm.conf
%config(noreplace) %{_sysconfdir}/yate/sigtransport.conf
%config(noreplace) %{_sysconfdir}/yate/isupmangler.conf
%config(noreplace) %{_sysconfdir}/yate/monitoring.conf
%config(noreplace) %{_sysconfdir}/yate/ysnmpagent.conf
%config(noreplace) %{_sysconfdir}/yate/users.conf
%config(noreplace) %{_sysconfdir}/yate/presence.conf
%config(noreplace) %{_sysconfdir}/yate/subscription.conf
%config(noreplace) %{_sysconfdir}/yate/jabberclient.conf
%config(noreplace) %{_sysconfdir}/yate/jabberserver.conf
%config(noreplace) %{_sysconfdir}/yate/jbfeatures.conf

View File

@ -4,7 +4,7 @@
# override DESTDIR at install time to prefix the install directory
DESTDIR :=
SUBDIRS := help skins scripts sounds
SUBDIRS := data help skins scripts sounds
prefix = @prefix@
exec_prefix = @exec_prefix@

38
share/data/Makefile.in Normal file
View File

@ -0,0 +1,38 @@
# Makefile
# This file holds the make rules for miscellaneous Yate data files
# override DESTDIR at install time to prefix the install directory
DESTDIR :=
DATA := snmp_mib.conf \
NULL-TEAM-MIB.txt YATE-MIB.txt
prefix = @prefix@
exec_prefix = @exec_prefix@
datarootdir = @datarootdir@
datadir = @datadir@
shrdir = $(datadir)/yate
datdir = $(shrdir)/data
# include optional local make rules
-include YateLocal.mak
.PHONY: all
all:
.PHONY: install
install:
@cd @srcdir@ && mkdir -p "$(DESTDIR)$(datdir)/" && \
test -z "$(DATA)" || \
install -m 0644 $(DATA) "$(DESTDIR)$(datdir)/"
.PHONY: uninstall
uninstall:
@-for i in $(DATA) ; do \
rm "$(DESTDIR)$(datdir)/$$i" ; \
done;
@-rmdir "$(DESTDIR)$(datdir)"
@-rmdir "$(DESTDIR)$(datdir)"
Makefile: @srcdir@/Makefile.in ../../config.status
cd ../.. && ./config.status

View File

@ -0,0 +1,24 @@
NULL-TEAM-MIB DEFINITIONS ::= BEGIN
IMPORTS
enterprises, MODULE-IDENTITY
FROM SNMPv2-SMI;
null-team MODULE-IDENTITY
LAST-UPDATED "200910201200Z"
ORGANIZATION "S.C. Null Team Impex S.R.L."
CONTACT-INFO
"Diana Cionoiu
phone: +40726088939
office: +40316201400
Email: office@null.ro"
DESCRIPTION
"Null Team's private-enterprise MIB."
REVISION "200910201200Z"
DESCRIPTION
"Initial revision."
::= { enterprises 34501 }
END

1773
share/data/YATE-MIB.txt Normal file

File diff suppressed because it is too large Load Diff

1464
share/data/snmp_mib.conf Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
# Makefile
# This file holds the make rules for Yate script files
# This file holds the make rules for Yate sound files
# override DESTDIR at install time to prefix the install directory
DESTDIR :=