Major rewrite of signalling components creation and configuration.
The creation of subcomponents is offloaded to each component to allow for proper building of the component stack. git-svn-id: http://voip.null.ro/svn/yate@2650 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
663b3ad280
commit
a46886c059
|
@ -0,0 +1,61 @@
|
|||
;[session]
|
||||
; Each such section configures parameters for talking to a Cisco Session Manager
|
||||
; The name of the section is referenced by session users
|
||||
; You can have a single session to each Cisco Session Manager
|
||||
; Most parameters are related to the RUDP protocol
|
||||
|
||||
; rudp_sequence: int: Initial RUDP sequence number, 0-255
|
||||
;rudp_sequence=0
|
||||
|
||||
; rudp_maxretrans: int: Maximum retransmissions until RUDP is disconnected
|
||||
;rudp_maxretrans=2
|
||||
|
||||
; rudp_maxcumulative: int: Maximum number of segments in a cumulative ACK
|
||||
;rudp_maxcumulative=3
|
||||
|
||||
; rudp_retransmission: int: RUDP retransmission interval in ms, 400+
|
||||
;rudp_retransmission=600
|
||||
|
||||
; rudp_cumulative: int: RUDP cumulative ACK send timer in ms, 100+
|
||||
;rudp_cumulative=300
|
||||
|
||||
; rudp_nulltimer: int: RUDP NULL transmission timer in ms, 1500+
|
||||
;rudp_nulltimer=2000
|
||||
|
||||
; rudp_syntimer: int: RUDP SYN transmission timer in ms, 900+
|
||||
;rudp_syntimer=1000
|
||||
|
||||
; rudp_checksum: bool: Attach RUDP checksums in sent packets
|
||||
;rudp_checksum=no
|
||||
|
||||
; rudp_sendsyn: bool: Actively send RUDP SYN when connection is down
|
||||
;rudp_sendsyn=no
|
||||
|
||||
; remote_host: ipaddr: IPv6 address of remote Cisco SM, mandatory
|
||||
;remote_host=
|
||||
|
||||
; remote_port: int: Port for RUDP on remote Cisco SM
|
||||
;remote_port=8060
|
||||
|
||||
; local_host: ipaddr: Address of local interface, zero address for kernel default
|
||||
;local_host=0.0.0.0
|
||||
|
||||
; local_port: int: Local UDP port number for RUDP session
|
||||
;local_port=same as remote_port
|
||||
|
||||
|
||||
;[slt_name]
|
||||
; SLT sections create on demand SS7 Layer 2 transports (remote MTP2 links)
|
||||
; The name of the section is referenced as link= from a MTP3 configuration
|
||||
|
||||
; session: string: Name of section describing the Cisco Session Manager to use
|
||||
;session=session
|
||||
|
||||
; channel: int: Number of the channel inside the session, must match remote config
|
||||
;channel=0
|
||||
|
||||
; configuration: int: Configuration request retransmission interval in ms, 250+
|
||||
;configuration=5000
|
||||
|
||||
; printslt: bool: Display SLT communication for debugging purposes
|
||||
;printslt=no
|
|
@ -0,0 +1,26 @@
|
|||
; Configuration for each TDMV API span on available wanpipe cards
|
||||
|
||||
[general]
|
||||
; This section configures common settings and defaults for all interfaces
|
||||
|
||||
; buflen: int: Size of data buffer in bytes
|
||||
;buflen=160
|
||||
|
||||
; idlevalue: int: Byte value to use as filler when no data is available
|
||||
;idlevalue=255
|
||||
|
||||
; priority: keyword: Data thread priority: normal, high, highest
|
||||
;priority=normal
|
||||
|
||||
|
||||
;[tdm1]
|
||||
; Each such section configures a Layer 1 TDM interface
|
||||
; The section name is referenced from upper layers to create signalling
|
||||
; interfaces (like D channels) and voice circuit groups (B channels)
|
||||
; The buflen, idlevalue and priority can be overriden in each section
|
||||
|
||||
; span: int: TDM span number as configured in wanrouter configuration
|
||||
;span=1
|
||||
|
||||
; type: keyword: Type of the interface, one of: E1, T1, NET, CPE
|
||||
;type=E1
|
|
@ -1,72 +1,87 @@
|
|||
; This file keep signalling channel configuration
|
||||
; Each section (except for 'general' section) configure a link
|
||||
; For call controllers, the name of the section will be used to route outgoing calls
|
||||
; Each section (except for 'general' section) configure a call controller (trunk)
|
||||
; or a signalling component
|
||||
; For call controllers (trunks), the name of the section will be used to route
|
||||
; outgoing calls
|
||||
|
||||
|
||||
[general]
|
||||
; This section keep general settings for the signalling module:
|
||||
; - Default values for missing or invalid parameters in link sections
|
||||
; This section keep general or default settings for the signalling module:
|
||||
|
||||
; debuglevel: string: Comma separated list of debug levels for module and SS7 components
|
||||
; Set to 0 to disable any debug message or -1 (or void) to left it unchanged
|
||||
; Keep in mind that all objects are chained in module, so any subsequent changes in
|
||||
; module's debug level is propagated to the SS7 objects
|
||||
; The order is: Module, Signalling engine, SS7 router, SS7 management, SS7 maintenance
|
||||
; debuglevel: int: Debug level for the plugin
|
||||
; This parameter is applied on reload
|
||||
;debuglevel=
|
||||
|
||||
; debuglevel_engine: int: Debug level for the signalling engine
|
||||
; This parameter is applied on reload
|
||||
;debuglevel_engine=
|
||||
|
||||
;Example of an 'isdn-pri-net' link
|
||||
;[link1]
|
||||
; dtmfinband: boolean: Enable to try to send the DTMF data in band when an audio
|
||||
; channel is available. If disabled or no audio channel available, the DTMF will
|
||||
; be sent through the signalling channel if any
|
||||
;dtmfinband=no
|
||||
|
||||
; type: string: Specify the link type
|
||||
|
||||
; Each section except [general] can have some common parameters
|
||||
|
||||
; To disable the component without deleting the entire section.
|
||||
; The default is to enable the component
|
||||
; enable: bool: Allow creation of the component corresponding to the section
|
||||
;enable=yes
|
||||
|
||||
; Debug name as reported in Yate logs, default is derived from component name
|
||||
; This parameter is used only when a component is created
|
||||
; debugname: string: Debug name of the created component
|
||||
;debugname=
|
||||
|
||||
; Debug level to apply on creation or reload
|
||||
; debuglevel: int: Debug level of the component
|
||||
;debuglevel=
|
||||
|
||||
|
||||
; Example of an ISDN trunk
|
||||
;[trunk1]
|
||||
|
||||
; type: keyword: Specify the trunk type
|
||||
; Allowed values:
|
||||
; ss7-isup: SS7 ISDN User Part over synchronous (HDLC) interface(s)
|
||||
; isdn-bri-net: ISDN network side of a data link over basic rate HDLC interface(s)
|
||||
; isdn-bri-cpe: ISDN CPE (user) side of a data link over basic rate HDLC interface(s)
|
||||
; isdn-pri-net: ISDN network side of a data link over one or more primary HDLC interface(s)
|
||||
; isdn-pri-cpe: ISDN CPE (user) side of a data link over one or more primary HDLC interface(s)
|
||||
; isdn-pri-mon: ISDN monitor of one or more primary HDLC interface(s)
|
||||
; NOTE: isdn-pri-net and isdn-pri-cpe are identical, except for the side of the link
|
||||
;type=isdn-pri-net
|
||||
|
||||
; enable: boolean: Enable or disable this call controller
|
||||
; yes: Create this call controller. If already exists, apply settings (the settings
|
||||
; that can be changed on reload are explicitely specified in place)
|
||||
; no: Remove call controller if already created
|
||||
; Defaults to yes
|
||||
;enable=yes
|
||||
|
||||
; sig: string: Specify the span(s) containing the signalling channel(s)
|
||||
; For example wanpipe1 or any other section specified in any of the telephony
|
||||
; modules like wpcard or zapcard
|
||||
; Ignored if type is isdn-pri-mon
|
||||
;sig=wanpipe1
|
||||
|
||||
; voice: string: Specify the span(s) containing the voice channel(s)
|
||||
; Multiple cards may be specified by simply separating them with a comma (',') character
|
||||
; Defaults to the span specified in the sig parameter
|
||||
; Ignored if type is isdn-pri-mon
|
||||
;voice=
|
||||
;type=
|
||||
|
||||
; switchtype: string: The switch type of this group
|
||||
; This parameter refers only to ISDN. It defines a set of flags modifying the
|
||||
; call controller's behaviour
|
||||
; This parameter defines a set of flags modifying the call controller's behaviour
|
||||
; Allowed values: euro-isdn-e1, euro-isdn-t1, national-isdn, dms100, lucent5e, att4ess, qsig, unknown
|
||||
; Defaults to unknown
|
||||
;switchtype=
|
||||
;switchtype=unknown
|
||||
|
||||
; dtmfinband: boolean: Enable to try to send the DTMF data in band when an audio channel is available
|
||||
; If disabled or no audio channel available, the DTMF will be sent through the signalling channel if any
|
||||
; Defaults to disable
|
||||
;dtmfinband = disable
|
||||
; sig: string: Specify the span(s) containing the signalling channel (D)
|
||||
; For example wanpipe1 or any other section specified in any of the telephony
|
||||
; modules like wpcard or zapcard
|
||||
;sig=
|
||||
|
||||
; voice: string: Specify the span(s) containing the voice channels (B)
|
||||
; Multiple cards may be specified by simply separating them with a comma (',')
|
||||
; character
|
||||
; Defaults to the trunk name if missing
|
||||
;voice=
|
||||
|
||||
; number: string: Prefix of numbers we accept call setups for, empty to accept all
|
||||
; Only used by isdn-pri-cpe, makes sense when NET side is Point-to-Multipoint
|
||||
; Setups are ignored if called number is present but doesn't start with this prefix
|
||||
;number=
|
||||
|
||||
; rxunderrun: int: Maximum interval in ms between two packets before we report
|
||||
; an underrun condition, zero to disable or 2500+
|
||||
;rxunderrun=0
|
||||
|
||||
; strategy: string: The strategy used to allocate voice channels for outgoing calls
|
||||
; Allowed values:
|
||||
; - increment Do an incremental search for an idle channel starting with the last allocated channel
|
||||
; - decrement Do an decremental search for an idle channel starting with the last allocated channel
|
||||
; - lowest Do an incremental search for an idle channel starting with the first channel in group
|
||||
; - highest Do an decremental search for an idle channel starting with the last channel in group
|
||||
; - increment Incremental search an idle channel starting with the last allocated channel
|
||||
; - decrement Decremental search an idle channel starting with the last allocated channel
|
||||
; - lowest Incremental search an idle channel starting with the first channel in group
|
||||
; - highest Decremental search an idle channel starting with the last channel in group
|
||||
; - random Randomly choose an idle channel
|
||||
; Defaults to increment
|
||||
;strategy=increment
|
||||
|
@ -76,21 +91,20 @@
|
|||
; Allowed values:
|
||||
; even Allocate only even channels
|
||||
; odd Allocate only odd channels
|
||||
; even-fallback Allocate even channels. Fallback to odd channels when no more even channels
|
||||
; odd-fallback Allocate odd channels. Fallback to even channels when no more odd channels
|
||||
; even-fallback Allocate even channels, fall back to odd channels
|
||||
; odd-fallback Allocate odd channels, fall back to even channels
|
||||
;strategy-restrict=
|
||||
|
||||
; channelsync: integer: The interval (in seconds) at which the call controller
|
||||
; will try to re-sync idle channels
|
||||
; The call controller will notify the other side of the link of idle channels
|
||||
; Set to 0 to disable
|
||||
; Defaults to minimum value if missing or invalid
|
||||
; Defaults to minimum value (500s) if missing or invalid
|
||||
;channelsync=1000
|
||||
|
||||
; numplan: string: Default numbering plan for outgoing calls
|
||||
; Values: unknown, isdn, data, telex, national, private
|
||||
; Defaults to unknown if missing or incorrect
|
||||
; This parameter refers only to ISDN
|
||||
;numplan=unknown
|
||||
|
||||
; numtype: string: Default number type for outgoing calls
|
||||
|
@ -108,78 +122,72 @@
|
|||
; Defaults to user-provided if missing or incorrect
|
||||
;screening=user-provided
|
||||
|
||||
; earlyacm: boolean: Convert received early ACM user state into progress or ringing
|
||||
; Defaults to enable
|
||||
;earlyacm=enable
|
||||
|
||||
; format: string: Default data format for outgoing calls. Values: alaw, mulaw, g721
|
||||
; Defaults to alaw if missing or incorrect
|
||||
; alaw is used commonly in Europe while mulaw is used commonly in US and Japan.
|
||||
;format=alaw
|
||||
|
||||
; number: string: Prefix of numbers we accept call setups for, empty to accept all
|
||||
; Only used in ISDN BRI CPE, makes sense when NET side is Point-to-Multipoint
|
||||
; Setups are ignored if called number is present but doesn't start with this prefix
|
||||
;number=
|
||||
|
||||
; print-layer2PDU: boolean: Print layer 2 (Q.921) protocol data units to output
|
||||
; For ISDN this option is applied on reload
|
||||
; Defaults to no
|
||||
;print-layer2PDU=no
|
||||
|
||||
; print-layer3PDU: boolean: Print layer 3 (Q.931) protocol data units to output
|
||||
; For ISDN this option is applied on reload
|
||||
; Defaults to no
|
||||
;print-layer3PDU=no
|
||||
|
||||
; print-layer4PDU: boolean: Print layer 4 (SS7-ISUP) protocol data units to output
|
||||
; print-messages: boolean: Print decoded protocol data units to output
|
||||
; This option is applied on reload
|
||||
; Defaults to no
|
||||
;print-layer4PDU=no
|
||||
;print-messages=no
|
||||
|
||||
; extended-debug: boolean: Print extented debug data (such as raw hex data) to output
|
||||
; For ISDN this parameter is used in conjuction with print-layer2PDU and print-layer3PDU and
|
||||
; is ignored if it's pair is not enabled
|
||||
; For SS7 this parameter is used in conjuction with print-layer4PDU and
|
||||
; is ignored if it's pair is not enabled
|
||||
; print-frames: boolean: Print decoded Layer 2 (Q.921) frames to output
|
||||
; This option is applied on reload
|
||||
; Defaults to no
|
||||
;print-frames=no
|
||||
|
||||
; extended-debug: boolean: Print extended debug data (such as raw hex data) to output
|
||||
; This option is applied on reload
|
||||
; Defaults to no
|
||||
;extended-debug=no
|
||||
|
||||
; layer2dump: string: Filename to dump Q.921 packets to
|
||||
;layer2dump=
|
||||
|
||||
; layer3dump: string: Filename to dump Q.931 packets to
|
||||
;layer3dump=
|
||||
|
||||
|
||||
; Example of an ISDN passive recorder
|
||||
;[recorder1]
|
||||
|
||||
; type: keyword: Specify the trunk type
|
||||
; Allowed values:
|
||||
; isdn-pri-mon: ISDN monitor of one or more primary HDLC interface(s)
|
||||
;type=isdn-pri-mon
|
||||
|
||||
; sig-net: string: Specify the span(s) containing the signalling channel(s) for the network side of the monitored link
|
||||
; For example wanpipe1 or any other section specified in any of the telephony
|
||||
; modules like wpcard or zapcard
|
||||
; Ignored if type is not isdn-pri-mon
|
||||
;sig-net=
|
||||
|
||||
; sig-cpe: string: Specify the span(s) containing the signalling channel(s) for the user side of the monitored link
|
||||
; For example wanpipe1 or any other section specified in any of the telephony
|
||||
; modules like wpcard or zapcard
|
||||
; Ignored if type is not isdn-pri-mon
|
||||
;sig-cpe=
|
||||
|
||||
; voice-net: string: Specify the span(s) containing the voice channel(s) for the network side of the monitored link
|
||||
; Multiple cards may be specified by simply separating them with a comma (',') character
|
||||
; Defaults to the span specified in the sig-net parameter
|
||||
; Ignored if type is not isdn-pri-mon
|
||||
;voice-net=
|
||||
|
||||
; voice-cpe: string: Specify the span(s) containing the voice channel(s) for the user side of the monitored link
|
||||
; Multiple cards may be specified by simply separating them with a comma (',') character
|
||||
; Defaults to the span specified in the sig-cpe parameter
|
||||
; Ignored if type is not isdn-pri-mon
|
||||
;voice-cpe=
|
||||
|
||||
; detect: boolean: Change the side of the link on each captured request for watched signalling span(s)
|
||||
; If disabled and the side of the link is not correct, the monitor will not be notified on
|
||||
; data link state change. This may lead to malfunction
|
||||
; Defaults to enable
|
||||
; Ignored if type is not isdn-pri-mon
|
||||
;detect=enable
|
||||
;detect=yes
|
||||
|
||||
; idletimeout: integer: HDLC data link idle timeout, should be 3 * T203
|
||||
; The minimum allowed value is 4000ms. Defaults to 30000 if missing or invalid
|
||||
;idletimeout=30000
|
||||
|
||||
; muxchanbuffer: integer: The buffer size for one channel of the audio multiplexer
|
||||
; Defaults to 160 if 0 or missing
|
||||
; Ignored if type is not isdn-pri-mon
|
||||
;muxchanbuffer=160
|
||||
|
||||
; idlevalue: integer: The value used by the audio multiplexer to fill missing data
|
||||
|
@ -189,21 +197,21 @@
|
|||
; Ignored if type is not isdn-pri-mon
|
||||
;idlevalue=255
|
||||
|
||||
; idletimeout: integer: HDLC data link idle timeout, should be 3 * T203
|
||||
; The minimum allowed value is 4000. Defaults to 30000 if missing or invalid
|
||||
; Ignored if type is not isdn-pri-mon
|
||||
;idletimeout=30000
|
||||
; layer2dump-net: string: Filename to dump NET Q.921 packets to
|
||||
;layer2dump-net=
|
||||
|
||||
; emergency: boolean: Emergency align SS7 MTP2 layer at startup
|
||||
; Defaults to no
|
||||
;emergency=yes
|
||||
; layer2dump-cpe: string: Filename to dump CPE Q.921 packets to
|
||||
;layer2dump-cpe=
|
||||
|
||||
; rxunderruninterval: integer: The interval (in miliseconds) allowed between
|
||||
; 2 packets received on the signalling channel (required)
|
||||
; Minimum value is 5 for SS7 links and 3000 for ISDN links
|
||||
;rxunderruninterval=10
|
||||
|
||||
; pointcodetype: string: SS7 point code type for ISUP (required)
|
||||
; Example of a SS7 ISUP trunk
|
||||
;[isup1]
|
||||
; type: keyword: Specify the trunk type
|
||||
; Allowed values:
|
||||
; ss7-isup: SS7 ISDN User Part
|
||||
;type=ss7-isup
|
||||
|
||||
; pointcodetype: string: SS7 point code type (required)
|
||||
; Allowed values:
|
||||
; ITU ITU-T Q.704
|
||||
; ANSI ANSI T1.111.4
|
||||
|
@ -213,61 +221,142 @@
|
|||
; Japan5 5-bit SLS
|
||||
;pointcodetype=
|
||||
|
||||
; pointcode: string: Point code serviced by this link
|
||||
; The format is network-cluster-member
|
||||
; Parameter pointcode may be repeated to add more local point codes
|
||||
;pointcode=
|
||||
|
||||
; defaultpointcode: string: Default originating point code used for outgoing calls
|
||||
; If missing or invalid the first point code added to MTP3 is used
|
||||
; If no point codes are added no calls can be made (incoming or outgoing)
|
||||
; through this trunk
|
||||
; The format is network-cluster-member
|
||||
; If missing or invalid the first point code added is used
|
||||
; If no point codes are added no calls can be made (incoming or outgoing) through this link
|
||||
;defaultpointcode=
|
||||
|
||||
; remotepointcode: string: Default destination point code used for outgoing calls and maintenance messages
|
||||
; remotepointcode: string: Default destination point code used for outgoing
|
||||
; calls and maintenance messages
|
||||
; If missing or invalid, no maintenance message will be sent
|
||||
; The format is network-cluster-member
|
||||
;remotepointcode=
|
||||
|
||||
; netind2pctype: string: Comma separated list of point code types used to map an incoming
|
||||
; network indicator to a specific point code type
|
||||
; earlyacm: boolean: Convert received early ACM user state into progress or ringing
|
||||
;earlyacm=yes
|
||||
|
||||
; voice: string: Specify the span(s) containing the voice channels (L1)
|
||||
; Multiple cards may be specified by simply separating them with a comma (',')
|
||||
; character
|
||||
; Defaults to the trunk name if missing
|
||||
;voice=
|
||||
|
||||
; strategy: string: The strategy used to allocate voice channels for outgoing calls
|
||||
; Allowed values:
|
||||
; - increment Incremental search an idle channel starting with the last allocated channel
|
||||
; - decrement Decremental search an idle channel starting with the last allocated channel
|
||||
; - lowest Incremental search an idle channel starting with the first channel in group
|
||||
; - highest Decremental search an idle channel starting with the last channel in group
|
||||
; - random Randomly choose an idle channel
|
||||
; Defaults to increment
|
||||
;strategy=increment
|
||||
|
||||
; strategy-restrict: string: Define channel allocation restrictions and behaviour
|
||||
; This option is ignored when strategy is random
|
||||
; Allowed values:
|
||||
; even Allocate only even channels
|
||||
; odd Allocate only odd channels
|
||||
; even-fallback Allocate even channels, fall back to odd channels
|
||||
; odd-fallback Allocate odd channels, fall back to even channels
|
||||
;strategy-restrict=
|
||||
|
||||
; channelsync: integer: The interval (in seconds) at which the call controller
|
||||
; will try to re-sync idle channels
|
||||
; The call controller will notify the other side of the link of idle channels
|
||||
; Set to 0 to disable
|
||||
; Defaults to minimum value (60s) if missing or invalid
|
||||
;channelsync=1000
|
||||
|
||||
; numplan: string: Default numbering plan for outgoing calls
|
||||
; Values: unknown, isdn, data, telex, national, private
|
||||
; Defaults to unknown if missing or incorrect
|
||||
;numplan=unknown
|
||||
|
||||
; numtype: string: Default number type for outgoing calls
|
||||
; Values: unknown,international,national,net-specific,subscriber,abbreviated,reserved
|
||||
; Defaults to unknown if missing or incorrect
|
||||
;numtype=unknown
|
||||
|
||||
; presentation: string: Default number presentation for outgoing calls
|
||||
; Values: allowed, restricted, unavailable
|
||||
; Defaults to allowed if missing or incorrect
|
||||
;presentation=allowed
|
||||
|
||||
; screening: string: Default number screening for outgoing calls
|
||||
; Values: user-provided, user-provided-passed, user-provided-failed, network-provided
|
||||
; Defaults to user-provided if missing or incorrect
|
||||
;screening=user-provided
|
||||
|
||||
; format: string: Default data format for outgoing calls. Values: alaw, mulaw, g721
|
||||
; Defaults to alaw if missing or incorrect
|
||||
; alaw is used commonly in Europe while mulaw is used commonly in US and Japan.
|
||||
;format=alaw
|
||||
|
||||
; print-messages: boolean: Print decoded protocol data units to output
|
||||
; This option is applied on reload
|
||||
; Defaults to no
|
||||
;print-messages=no
|
||||
|
||||
; extended-debug: boolean: Print extended debug data (such as raw hex data) to output
|
||||
; This option is applied on reload
|
||||
; Defaults to no
|
||||
;extended-debug=no
|
||||
|
||||
|
||||
; Example of a SS7 MTP3 network (linkset)
|
||||
;[linkset1]
|
||||
; type: keyword: Specify the linkset type
|
||||
; Allowed values:
|
||||
; ss7-mtp3: SS7 Message Transfer Part - Layer 3
|
||||
;type=ss7-mtp3
|
||||
|
||||
; netind2pctype: string: Comma separated list of point code types used to map an
|
||||
; incoming network indicator to a specific point code type
|
||||
; This option is required and is used to configure a SS7 MTP3 network
|
||||
; The list must contain 4 values indicating the point code type for International,
|
||||
; SpareInternational, National and ReservedNational network indicators
|
||||
; See the pointcodetype option for allowed values
|
||||
; NOTE: If an incoming packet comes with an unconfigured network indicator it will be dropped
|
||||
; The list must contain either a singe type or 4 values indicating the point
|
||||
; code type for International, SpareInternational, National and ReservedNational
|
||||
; network indicators
|
||||
; If only a single type is specified it will be used to configure all types of
|
||||
; network indicators
|
||||
; See the ISUP pointcodetype option for allowed values
|
||||
; NOTE: An incoming packet with an unconfigured network indicator will be dropped
|
||||
; Examples:
|
||||
; netind2pctype=ITU,ITU,ITU,ITU
|
||||
; netind2pctype=ITU
|
||||
; netind2pctype=ITU,ANSI,ITU,ITU
|
||||
; netind2pctype=ANSI8,ITU,ANSI,ITU
|
||||
;netind2pctype=
|
||||
|
||||
; route: string: Build a destination route for a SS7 MTP3 network
|
||||
; route: string: Build a destination route for the SS7 network
|
||||
; The format of this option is pointcodetype,label,priority
|
||||
; This parameter can be repeated to build multiple destination routes
|
||||
; The network will notify the router about its destination(s) and priority
|
||||
; Example: route=ITU,2-2-2,0
|
||||
;route=
|
||||
|
||||
; filllink: boolean: Configure MTP2 to request link fill (packet repeat) when sending
|
||||
; FISU/LSSU packets
|
||||
; Defaults to yes
|
||||
;filllink=yes
|
||||
|
||||
; debuglevel: string: Comma separated list of debug levels for link layers
|
||||
; Set to 0 to disable any debug message or -1 (or void) to left it unchanged
|
||||
; ss7-isup: Interface,Circuit group, MTP2, MTP3, ISUP
|
||||
; isdn-pri-net,isdn-pri-cpe: Interface,Circuit group, Q921, Q931
|
||||
;debuglevel=
|
||||
|
||||
; layer2dump: string: Filename to dump Q.921 or MTP2 packets to (if applicable)
|
||||
;layer2dump=
|
||||
|
||||
; layer3dump: string: Filename to dump Q.931 or MTP3 packets to (if applicable)
|
||||
; layer3dump: string: Filename to dump MTP3 packets to
|
||||
;layer3dump=
|
||||
|
||||
; layer2dump-net: string: Filename to dump NET Q.921 packets to (passive only)
|
||||
;layer2dump-net=
|
||||
|
||||
; layer2dump-cpe: string: Filename to dump CPE Q.921 packets to (passive only)
|
||||
;layer2dump-cpe=
|
||||
|
||||
; Example of a SS7 MTP2 link
|
||||
;[link1]
|
||||
; type: keyword: Specify the link type
|
||||
; Allowed values:
|
||||
; ss7-mtp2: SS7 Message Transfer Part - Layer 2
|
||||
;type=ss7-mtp2
|
||||
|
||||
; emergency: boolean: Emergency align SS7 MTP2 layer at startup
|
||||
;emergency=yes
|
||||
|
||||
; filllink: boolean: Configure MTP2 to request link fill (packet repeat) when
|
||||
; sending FISU or LSSU packets
|
||||
;filllink=yes
|
||||
|
||||
; rxunderrun: int: Maximum interval in ms between two packets before we report
|
||||
; an underrun condition, zero to disable or 25+
|
||||
;rxunderrun=0
|
||||
|
||||
; layer2dump: string: Filename to dump MTP2 packets to
|
||||
;layer2dump=
|
||||
|
|
|
@ -52,12 +52,15 @@ private:
|
|||
using namespace TelEngine;
|
||||
|
||||
static ObjList s_factories;
|
||||
static Mutex s_mutex(true);
|
||||
static Mutex s_mutex(true,"SignallingFactory");
|
||||
|
||||
SignallingFactory::SignallingFactory()
|
||||
SignallingFactory::SignallingFactory(bool fallback)
|
||||
{
|
||||
s_mutex.lock();
|
||||
s_factories.append(this)->setDelete(false);
|
||||
if (!s_factories.find(this)) {
|
||||
ObjList* l = fallback ? s_factories.append(this) : s_factories.insert(this);
|
||||
l->setDelete(false);
|
||||
}
|
||||
s_mutex.unlock();
|
||||
}
|
||||
|
||||
|
@ -68,7 +71,7 @@ SignallingFactory::~SignallingFactory()
|
|||
s_mutex.unlock();
|
||||
}
|
||||
|
||||
void* SignallingFactory::build(const String& type, const NamedList* name)
|
||||
SignallingComponent* SignallingFactory::build(const String& type, const NamedList* name)
|
||||
{
|
||||
if (type.null())
|
||||
return 0;
|
||||
|
@ -80,29 +83,58 @@ void* SignallingFactory::build(const String& type, const NamedList* name)
|
|||
SignallingFactory* f = static_cast<SignallingFactory*>(l->get());
|
||||
if (!f)
|
||||
continue;
|
||||
XDebug(DebugAll,"Attempting to create a %s %s using factory %p",
|
||||
DDebug(DebugAll,"Attempting to create a '%s' %s using factory %p",
|
||||
name->c_str(),type.c_str(),f);
|
||||
void* obj = f->create(type,*name);
|
||||
SignallingComponent* obj = f->create(type,*name);
|
||||
if (obj)
|
||||
return obj;
|
||||
}
|
||||
lock.drop();
|
||||
DDebug(DebugInfo,"Factory creating default '%s' named '%s'",type.c_str(),name->c_str());
|
||||
// now build some objects we know about
|
||||
if (type == "SignallingEngine")
|
||||
return new SignallingEngine;
|
||||
else if (type == "SS7MTP2")
|
||||
if (type == "SS7MTP2")
|
||||
return new SS7MTP2(*name);
|
||||
else if (type == "SS7MTP3")
|
||||
return new SS7MTP3(*name);
|
||||
else if (type == "SS7Router")
|
||||
return new SS7Router(*name);
|
||||
else return 0;
|
||||
else if (type == "SS7Management")
|
||||
return new SS7Management(*name);
|
||||
else if (type == "SS7Maintenance")
|
||||
return new SS7Maintenance(*name);
|
||||
else if (type == "ISDNQ921")
|
||||
return new ISDNQ921(*name,*name);
|
||||
else if (type == "ISDNQ931")
|
||||
return new ISDNQ931(*name,*name);
|
||||
else if (type == "ISDNQ931Monitor")
|
||||
return new ISDNQ931Monitor(*name,*name);
|
||||
Debug(DebugMild,"Factory could not create '%s' named '%s'",type.c_str(),name->c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* SignallingFactory::buildInternal(const String& type, const NamedList* name)
|
||||
{
|
||||
SignallingComponent* c = build(type,name);
|
||||
if (!c)
|
||||
return 0;
|
||||
void* raw = c->getObject(type);
|
||||
if (!raw)
|
||||
Debug(DebugFail,"Built component %p could not be casted back to type '%s'",c,type.c_str());
|
||||
#ifdef DEBUG
|
||||
else
|
||||
Debug(DebugAll,"Built component %p type '%s' interface at %p",c,type.c_str(),raw);
|
||||
#endif
|
||||
return raw;
|
||||
}
|
||||
|
||||
|
||||
SignallingComponent::SignallingComponent(const char* name)
|
||||
SignallingComponent::SignallingComponent(const char* name, const NamedList* params)
|
||||
: m_engine(0)
|
||||
{
|
||||
if (params) {
|
||||
name = params->getValue("debugname",name);
|
||||
debugLevel(params->getIntValue("debuglevel",-1));
|
||||
}
|
||||
DDebug(engine(),DebugAll,"Component '%s' created [%p]",name,this);
|
||||
setName(name);
|
||||
}
|
||||
|
@ -129,6 +161,11 @@ const String& SignallingComponent::toString() const
|
|||
return m_name;
|
||||
}
|
||||
|
||||
bool SignallingComponent::initialize(const NamedList* config)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SignallingComponent::control(NamedList& params)
|
||||
{
|
||||
return false;
|
||||
|
@ -180,7 +217,7 @@ unsigned long SignallingComponent::tickSleep(unsigned long usec) const
|
|||
|
||||
|
||||
SignallingEngine::SignallingEngine(const char* name)
|
||||
: Mutex(true),
|
||||
: Mutex(true,"SignallingEngine"),
|
||||
m_thread(0), m_listChanged(true),
|
||||
m_usecSleep(DEF_TICK_SLEEP), m_tickSleep(0)
|
||||
{
|
||||
|
@ -195,33 +232,75 @@ SignallingEngine::~SignallingEngine()
|
|||
stop();
|
||||
}
|
||||
lock();
|
||||
unsigned int n = m_components.count();
|
||||
if (n)
|
||||
Debug(this,DebugNote,"Cleaning up %u components [%p]",n,this);
|
||||
m_components.clear();
|
||||
unlock();
|
||||
}
|
||||
|
||||
SignallingComponent* SignallingEngine::find(const String& name)
|
||||
{
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
return static_cast<SignallingComponent*>(m_components[name]);
|
||||
}
|
||||
|
||||
SignallingComponent* SignallingEngine::find(const String& name, const String& type, const SignallingComponent* start)
|
||||
{
|
||||
Lock mylock(this);
|
||||
ObjList* l = m_components.skipNull();
|
||||
if (start) {
|
||||
l = m_components.find(start);
|
||||
if (!l)
|
||||
return 0;
|
||||
l = l->skipNext();
|
||||
}
|
||||
for (; l; l = l->skipNext()) {
|
||||
SignallingComponent* c = static_cast<SignallingComponent*>(l->get());
|
||||
if ((name.null() || (c->toString() == name)) &&
|
||||
(type.null() || c->getObject(type)))
|
||||
return c;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool SignallingEngine::find(const SignallingComponent* component)
|
||||
{
|
||||
if (!component)
|
||||
return false;
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
return m_components.find(component) != 0;
|
||||
}
|
||||
|
||||
SignallingComponent* SignallingEngine::build(const String& type, const NamedList& params, bool init)
|
||||
{
|
||||
Lock mylock(this);
|
||||
SignallingComponent* c = find(params,type);
|
||||
if (c && c->alive()) {
|
||||
DDebug(this,DebugAll,"Engine returning existing component '%s' @%p [%p]",
|
||||
c->toString().c_str(),c,this);
|
||||
return c;
|
||||
}
|
||||
c = SignallingFactory::build(type,¶ms);
|
||||
XDebug(this,DebugAll,"Created component @%p [%p]",c,this);
|
||||
insert(c);
|
||||
if (init && c)
|
||||
c->initialize(¶ms);
|
||||
return c;
|
||||
}
|
||||
|
||||
void SignallingEngine::insert(SignallingComponent* component)
|
||||
{
|
||||
if (!component)
|
||||
return;
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
if (component->engine() == this)
|
||||
return;
|
||||
DDebug(this,DebugAll,"Engine inserting component '%s' @%p [%p]",
|
||||
component->toString().c_str(),component,this);
|
||||
#ifdef DEBUG
|
||||
const char* dupl = m_components.find(component->toString()) ? " (duplicate)" : "";
|
||||
Debug(this,DebugAll,"Engine inserting component '%s'%s @%p [%p]",
|
||||
component->toString().c_str(),dupl,component,this);
|
||||
#endif
|
||||
component->detach();
|
||||
component->m_engine = this;
|
||||
component->debugChain(this);
|
||||
|
@ -232,21 +311,21 @@ void SignallingEngine::remove(SignallingComponent* component)
|
|||
{
|
||||
if (!component)
|
||||
return;
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
if (component->engine() != this)
|
||||
return;
|
||||
DDebug(this,DebugAll,"Engine removing component @%p '%s' [%p]",
|
||||
component,component->toString().c_str(),this);
|
||||
m_components.remove(component,false);
|
||||
component->m_engine = 0;
|
||||
component->detach();
|
||||
m_components.remove(component,false);
|
||||
}
|
||||
|
||||
bool SignallingEngine::remove(const String& name)
|
||||
{
|
||||
if (name.null())
|
||||
return false;
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
SignallingComponent* component = find(name);
|
||||
if (!component)
|
||||
return false;
|
||||
|
@ -261,7 +340,7 @@ bool SignallingEngine::remove(const String& name)
|
|||
bool SignallingEngine::control(NamedList& params)
|
||||
{
|
||||
bool ok = false;
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
for (ObjList* l = m_components.skipNull(); l; l = l->skipNext())
|
||||
ok = static_cast<SignallingComponent*>(l->get())->control(params) || ok;
|
||||
return ok;
|
||||
|
@ -269,7 +348,7 @@ bool SignallingEngine::control(NamedList& params)
|
|||
|
||||
bool SignallingEngine::start(const char* name, Thread::Priority prio, unsigned long usec)
|
||||
{
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
if (m_thread)
|
||||
return m_thread->running();
|
||||
// defaults and sanity checks
|
||||
|
|
|
@ -99,11 +99,9 @@ bool SignallingInterface::notify(Notification event)
|
|||
}
|
||||
|
||||
|
||||
YCLASSIMP(SignallingReceiver,SignallingComponent)
|
||||
|
||||
SignallingReceiver::SignallingReceiver(const char* name)
|
||||
: SignallingComponent(name),
|
||||
m_ifaceMutex(true), m_interface(0)
|
||||
m_ifaceMutex(true,"SignallingReceiver::interface"), m_interface(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -111,30 +109,36 @@ SignallingReceiver::~SignallingReceiver()
|
|||
{
|
||||
if (m_interface)
|
||||
Debug(this,DebugGoOn,"Destroyed with interface (%p) attached",m_interface);
|
||||
TelEngine::destruct(attach(0));
|
||||
}
|
||||
|
||||
void SignallingReceiver::attach(SignallingInterface* iface)
|
||||
SignallingInterface* SignallingReceiver::attach(SignallingInterface* iface)
|
||||
{
|
||||
Lock lock(m_ifaceMutex);
|
||||
if (m_interface == iface)
|
||||
return;
|
||||
return 0;
|
||||
SignallingInterface* tmp = m_interface;
|
||||
m_interface = iface;
|
||||
lock.drop();
|
||||
if (tmp) {
|
||||
const char* name = 0;
|
||||
if (engine() && engine()->find(tmp)) {
|
||||
name = tmp->toString().safe();
|
||||
if (tmp->receiver() == this) {
|
||||
Debug(this,DebugAll,"Detaching interface (%p,'%s') [%p]",
|
||||
tmp,tmp->toString().safe(),this);
|
||||
tmp->attach(0);
|
||||
}
|
||||
Debug(this,DebugAll,"Detached interface (%p,'%s') [%p]",tmp,name,this);
|
||||
else {
|
||||
Debug(this,DebugNote,"Interface (%p,'%s') was not attached to us [%p]",
|
||||
tmp,tmp->toString().safe(),this);
|
||||
tmp = 0;
|
||||
}
|
||||
}
|
||||
if (!iface)
|
||||
return;
|
||||
return tmp;
|
||||
Debug(this,DebugAll,"Attached interface (%p,'%s') [%p]",
|
||||
iface,iface->toString().safe(),this);
|
||||
insert(iface);
|
||||
iface->attach(this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool SignallingReceiver::notify(SignallingInterface::Notification event)
|
||||
|
|
|
@ -1381,13 +1381,6 @@ void SS7MsgISUP::toString(String& dest, const SS7Label& label, bool params,
|
|||
dest << enclose;
|
||||
}
|
||||
|
||||
void* SS7MsgISUP::getObject(const String& name) const
|
||||
{
|
||||
if (name == "SS7MsgISUP")
|
||||
return (void*)this;
|
||||
return SignallingMessage::getObject(name);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper functions used to transmit responses
|
||||
|
@ -1484,7 +1477,7 @@ SS7ISUPCall::~SS7ISUPCall()
|
|||
// received by the controller
|
||||
void SS7ISUPCall::stopWaitSegment(bool discard)
|
||||
{
|
||||
Lock lock(m_callMutex);
|
||||
Lock mylock(this);
|
||||
if (!m_sgmMsg)
|
||||
return;
|
||||
m_sgmRecvTimer.stop();
|
||||
|
@ -1508,7 +1501,7 @@ inline bool timeout(SS7ISUP* isup, SS7ISUPCall* call, SignallingTimer& timer,
|
|||
// Get an event from this call
|
||||
SignallingEvent* SS7ISUPCall::getEvent(const Time& when)
|
||||
{
|
||||
Lock lock(m_callMutex);
|
||||
Lock mylock(this);
|
||||
if (m_lastEvent || m_state == Released)
|
||||
return 0;
|
||||
SS7MsgISUP* msg = 0;
|
||||
|
@ -1605,7 +1598,7 @@ SignallingEvent* SS7ISUPCall::getEvent(const Time& when)
|
|||
// Send an event to this call
|
||||
bool SS7ISUPCall::sendEvent(SignallingEvent* event)
|
||||
{
|
||||
Lock lock(m_callMutex);
|
||||
Lock mylock(this);
|
||||
if (!event)
|
||||
return false;
|
||||
if (m_terminate || m_state == Released) {
|
||||
|
@ -1690,7 +1683,7 @@ void* SS7ISUPCall::getObject(const String& name) const
|
|||
// On failure set the termination flag and release the new circuit if valid
|
||||
bool SS7ISUPCall::replaceCircuit(SignallingCircuit* circuit)
|
||||
{
|
||||
Lock lock(m_callMutex);
|
||||
Lock mylock(this);
|
||||
clearQueue();
|
||||
if (m_state > Setup || !circuit || !outgoing()) {
|
||||
m_iamTimer.stop();
|
||||
|
@ -2015,31 +2008,38 @@ SS7ISUP* SS7ISUPCall::isup()
|
|||
* SS7ISUP
|
||||
*/
|
||||
SS7ISUP::SS7ISUP(const NamedList& params)
|
||||
: SignallingCallControl(params,"isup."),
|
||||
m_cicLen(2),
|
||||
m_type(SS7PointCode::Other),
|
||||
m_defPoint(0),
|
||||
m_remotePoint(0),
|
||||
m_priossf(0),
|
||||
m_sls(255),
|
||||
m_earlyAcm(true),
|
||||
m_inn(false),
|
||||
m_l3LinkUp(false),
|
||||
m_uptTimer(0),
|
||||
m_userPartAvail(true),
|
||||
m_uptCicCode(0),
|
||||
m_rscTimer(0),
|
||||
m_rscCic(0),
|
||||
m_lockTimer(0),
|
||||
m_lockNeed(true),
|
||||
m_hwFailReq(false),
|
||||
m_blockReq(false),
|
||||
m_lockCicCode(0),
|
||||
m_printMsg(false),
|
||||
m_extendedDebug(false)
|
||||
: SignallingComponent(params.safe("SS7ISUP"),¶ms),
|
||||
SignallingCallControl(params,"isup."),
|
||||
m_cicLen(2),
|
||||
m_type(SS7PointCode::Other),
|
||||
m_defPoint(0),
|
||||
m_remotePoint(0),
|
||||
m_priossf(0),
|
||||
m_sls(255),
|
||||
m_earlyAcm(true),
|
||||
m_inn(false),
|
||||
m_l3LinkUp(false),
|
||||
m_uptTimer(0),
|
||||
m_userPartAvail(true),
|
||||
m_uptCicCode(0),
|
||||
m_rscTimer(0),
|
||||
m_rscCic(0),
|
||||
m_lockTimer(0),
|
||||
m_lockNeed(true),
|
||||
m_hwFailReq(false),
|
||||
m_blockReq(false),
|
||||
m_lockCicCode(0),
|
||||
m_printMsg(false),
|
||||
m_extendedDebug(false)
|
||||
{
|
||||
setName(params.getValue("debugname","isup"));
|
||||
|
||||
#ifdef DEBUG
|
||||
if (debugAt(DebugAll)) {
|
||||
String tmp;
|
||||
params.dump(tmp,"\r\n ",'\'',true);
|
||||
Debug(this,DebugAll,"SS7ISUP::SS7ISUP(%p) [%p]%s",
|
||||
¶ms,this,tmp.c_str());
|
||||
}
|
||||
#endif
|
||||
const char* stype = params.getValue("pointcodetype");
|
||||
m_type = SS7PointCode::lookup(stype);
|
||||
if (m_type == SS7PointCode::Other) {
|
||||
|
@ -2087,8 +2087,8 @@ SS7ISUP::SS7ISUP(const NamedList& params)
|
|||
if (m_uptTimer.interval())
|
||||
m_userPartAvail = false;
|
||||
|
||||
setDebug(params.getBoolValue("print-layer4PDU",m_printMsg),
|
||||
params.getBoolValue("extended-debug",m_extendedDebug));
|
||||
setDebug(params.getBoolValue("print-messages",false),
|
||||
params.getBoolValue("extended-debug",false));
|
||||
|
||||
if (debugAt(DebugInfo)) {
|
||||
String s;
|
||||
|
@ -2117,13 +2117,37 @@ SS7ISUP::~SS7ISUP()
|
|||
Debug(this,DebugInfo,"ISUP Call Controller destroyed [%p]",this);
|
||||
}
|
||||
|
||||
bool SS7ISUP::initialize(const NamedList* config)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
String tmp;
|
||||
if (config && debugAt(DebugAll))
|
||||
config->dump(tmp,"\r\n ",'\'',true);
|
||||
Debug(this,DebugInfo,"SS7ISUP::initialize(%p) [%p]%s",config,this,tmp.c_str());
|
||||
#endif
|
||||
if (config) {
|
||||
debugLevel(config->getIntValue("debuglevel_isup",
|
||||
config->getIntValue("debuglevel",-1)));
|
||||
setDebug(config->getBoolValue("print-messages",false),
|
||||
config->getBoolValue("extended-debug",false));
|
||||
}
|
||||
if (engine() && !network()) {
|
||||
NamedList params("ss7router");
|
||||
if (config)
|
||||
static_cast<String&>(params) = config->getValue("router",params);
|
||||
if (params.toBoolean(true))
|
||||
SS7Layer4::attach(YOBJECT(SS7Router,engine()->build("SS7Router",params,true)));
|
||||
}
|
||||
return SS7Layer4::initialize(config);
|
||||
}
|
||||
|
||||
// Append a point code to the list of point codes serviced by this controller
|
||||
// Set default point code
|
||||
bool SS7ISUP::setPointCode(SS7PointCode* pc, bool def)
|
||||
{
|
||||
if (!(pc && pc->pack(m_type)))
|
||||
return false;
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
// Force default if we are not having one or the list is empty
|
||||
def = def || !m_defPoint || !m_pointCodes.skipNull();
|
||||
// Force not default if the received point code is the same as the default one
|
||||
|
@ -2149,7 +2173,7 @@ bool SS7ISUP::setPointCode(SS7PointCode* pc, bool def)
|
|||
// Check if the given point code is serviced by this controller
|
||||
SS7PointCode* SS7ISUP::hasPointCode(const SS7PointCode& pc)
|
||||
{
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
for (ObjList* o = m_pointCodes.skipNull(); o; o = o->skipNext()) {
|
||||
SS7PointCode* p = static_cast<SS7PointCode*>(o->get());
|
||||
if (*p == pc)
|
||||
|
@ -2188,7 +2212,7 @@ SignallingCall* SS7ISUP::call(SignallingMessage* msg, String& reason)
|
|||
SignallingCircuit* cic = 0;
|
||||
const char* range = msg->params().getValue("circuits");
|
||||
reason.clear();
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
// Check
|
||||
while (true) {
|
||||
if (!m_defPoint) {
|
||||
|
@ -2223,7 +2247,7 @@ SignallingCall* SS7ISUP::call(SignallingMessage* msg, String& reason)
|
|||
if (!m_rscCic && m_rscTimer.interval())
|
||||
m_rscTimer.start();
|
||||
// Drop lock and send the event
|
||||
lock.drop();
|
||||
mylock.drop();
|
||||
event->sendEvent();
|
||||
}
|
||||
TelEngine::destruct(msg);
|
||||
|
@ -2296,14 +2320,6 @@ void SS7ISUP::cleanup(const char* reason)
|
|||
clearCalls();
|
||||
}
|
||||
|
||||
// Get a pointer to this object or other data
|
||||
void* SS7ISUP::getObject(const String& name) const
|
||||
{
|
||||
if (name == "SS7ISUP")
|
||||
return (void*)this;
|
||||
return SS7Layer4::getObject(name);
|
||||
}
|
||||
|
||||
// Remove all links with other layers. Disposes the memory
|
||||
void SS7ISUP::destroyed()
|
||||
{
|
||||
|
@ -2317,7 +2333,7 @@ void SS7ISUP::destroyed()
|
|||
|
||||
void SS7ISUP::timerTick(const Time& when)
|
||||
{
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
if (!(m_l3LinkUp && circuits()))
|
||||
return;
|
||||
|
||||
|
@ -2344,7 +2360,8 @@ void SS7ISUP::timerTick(const Time& when)
|
|||
if (!m_lockTimer.timeout(when.msec()))
|
||||
return;
|
||||
Debug(this,DebugMild,"Circuit %sblocking timed out cic=%u map=%s",
|
||||
m_blockReq?"":"un",m_lockCicCode,m_lockMap.c_str());
|
||||
(m_blockReq ? "" : "un"),
|
||||
m_lockCicCode,m_lockMap.c_str());
|
||||
}
|
||||
if (sendLocalLock(when.msec()))
|
||||
return;
|
||||
|
@ -2378,17 +2395,19 @@ void SS7ISUP::notify(SS7Layer3* link, int sls)
|
|||
{
|
||||
if (!link)
|
||||
return;
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
m_l3LinkUp = link->operational(-1);
|
||||
// Reset remote user part's availablity state if supported
|
||||
// Reset remote user part's availability state if supported
|
||||
// Force UPT re-send
|
||||
if (m_uptTimer.interval() && !m_l3LinkUp) {
|
||||
m_uptTimer.stop();
|
||||
m_userPartAvail = false;
|
||||
}
|
||||
Debug(this,DebugInfo,
|
||||
"L3 (%p,'%s') is %soperational sls=%d. Remote User Part is %savailable",link,
|
||||
link->toString().safe(),m_l3LinkUp?"":"not ",sls,m_userPartAvail?"":"un");
|
||||
"L3 (%p,'%s') is %soperational sls=%d. Remote User Part is %savailable",
|
||||
link,link->toString().safe(),
|
||||
(m_l3LinkUp ? "" : "not "),sls,
|
||||
(m_userPartAvail ? "" : "un"));
|
||||
}
|
||||
|
||||
SS7MSU* SS7ISUP::buildMSU(SS7MsgISUP::Type type, unsigned char sio,
|
||||
|
@ -2913,7 +2932,8 @@ void SS7ISUP::processControllerMsg(SS7MsgISUP* msg, const SS7Label& label, int s
|
|||
case SS7MsgISUP::CNF: // Confusion
|
||||
// TODO: check if this message was received in response to RSC, UBL, UBK, CGB, CGU
|
||||
Debug(this,DebugNote,"%s with cause='%s' diagnostic='%s'",msg->name(),
|
||||
msg->params().getValue("CauseIndicators"),msg->params().getValue("CauseIndicators.diagnostic"));
|
||||
msg->params().getValue("CauseIndicators"),
|
||||
msg->params().getValue("CauseIndicators.diagnostic"));
|
||||
stopSGM = true;
|
||||
break;
|
||||
case SS7MsgISUP::RLC: // Release Complete
|
||||
|
@ -3124,8 +3144,10 @@ bool SS7ISUP::blockCircuit(unsigned int cic, bool block, bool remote, bool hwFai
|
|||
something = circuit->maintLock(block,remote,changed,changedState);
|
||||
|
||||
if (something) {
|
||||
Debug(this,DebugNote,"%slocked %s side of circuit %u. Current flags 0x%x",
|
||||
block?"B":"Unb",remote?"remote":"local",cic,circuit->locked(-1));
|
||||
Debug(this,DebugNote,"%s %s side of circuit %u. Current flags 0x%x",
|
||||
(block ? "Blocked" : "Unblocked"),
|
||||
(remote ? "remote" : "local"),
|
||||
cic,circuit->locked(-1));
|
||||
m_verifyEvent = true;
|
||||
}
|
||||
return true;
|
||||
|
@ -3133,7 +3155,7 @@ bool SS7ISUP::blockCircuit(unsigned int cic, bool block, bool remote, bool hwFai
|
|||
|
||||
SS7ISUPCall* SS7ISUP::findCall(unsigned int cic)
|
||||
{
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
for (ObjList* o = m_calls.skipNull(); o; o = o->skipNext()) {
|
||||
SS7ISUPCall* call = static_cast<SS7ISUPCall*>(o->get());
|
||||
if (call->id() == cic)
|
||||
|
@ -3223,22 +3245,17 @@ bool SS7ISUP::sendLocalLock(u_int64_t when)
|
|||
SS7MsgISUP* msg = 0;
|
||||
m_lockMap.assign(d,lockRange);
|
||||
if (m_lockMap.length() > 1 || m_hwFailReq) {
|
||||
if (m_blockReq)
|
||||
msg = new SS7MsgISUP(SS7MsgISUP::CGB,m_lockCicCode);
|
||||
else
|
||||
msg = new SS7MsgISUP(SS7MsgISUP::CGU,m_lockCicCode);
|
||||
if (m_hwFailReq)
|
||||
msg->params().addParam("GroupSupervisionTypeIndicator","hw-failure");
|
||||
else
|
||||
msg->params().addParam("GroupSupervisionTypeIndicator","maintenance");
|
||||
msg = new SS7MsgISUP((m_blockReq ? SS7MsgISUP::CGB : SS7MsgISUP::CGU),
|
||||
m_lockCicCode);
|
||||
msg->params().addParam("GroupSupervisionTypeIndicator",
|
||||
(m_hwFailReq ? "hw-failure" : "maintenance"));
|
||||
msg->params().addParam("RangeAndStatus",String(m_lockMap.length()));
|
||||
msg->params().addParam("RangeAndStatus.map",m_lockMap);
|
||||
}
|
||||
else
|
||||
if (m_blockReq)
|
||||
msg = new SS7MsgISUP(SS7MsgISUP::BLK,m_lockCicCode);
|
||||
else
|
||||
msg = new SS7MsgISUP(SS7MsgISUP::UBL,m_lockCicCode);
|
||||
else {
|
||||
msg = new SS7MsgISUP((m_blockReq ? SS7MsgISUP::BLK : SS7MsgISUP::UBL),
|
||||
m_lockCicCode);
|
||||
}
|
||||
SS7Label label(m_type,*m_remotePoint,*m_defPoint,m_sls);
|
||||
transmitMessage(msg,label,false);
|
||||
m_lockTimer.start(when);
|
||||
|
@ -3250,9 +3267,9 @@ bool SS7ISUP::sendLocalLock(u_int64_t when)
|
|||
* SS7BICC
|
||||
*/
|
||||
SS7BICC::SS7BICC(const NamedList& params)
|
||||
: SS7ISUP(params)
|
||||
: SignallingComponent(params.safe("SS7BICC"),¶ms),
|
||||
SS7ISUP(params)
|
||||
{
|
||||
setName(params.getValue("debugname","bicc"));
|
||||
m_cicLen = 4;
|
||||
Debug(this,DebugInfo,"BICC Call Controller [%p]",this);
|
||||
}
|
||||
|
@ -3269,14 +3286,6 @@ SS7MSU* SS7BICC::createMSU(SS7MsgISUP::Type type, unsigned char ssf,
|
|||
return buildMSU(type,SS7MSU::BICC | (ssf & 0xf0),label,cic,params);
|
||||
}
|
||||
|
||||
// Get a pointer to this object or other data
|
||||
void* SS7BICC::getObject(const String& name) const
|
||||
{
|
||||
if (name == "SS7BICC")
|
||||
return (void*)this;
|
||||
return SS7ISUP::getObject(name);
|
||||
}
|
||||
|
||||
bool SS7BICC::receivedMSU(const SS7MSU& msu, const SS7Label& label, SS7Layer3* network, int sls)
|
||||
{
|
||||
if (msu.getSIF() != SS7MSU::BICC || !hasPointCode(label.dpc()))
|
||||
|
|
|
@ -188,18 +188,25 @@ ObjList* SS7Layer2::recoverMSU()
|
|||
return 0;
|
||||
}
|
||||
|
||||
YCLASSIMP2(SS7MTP2,SS7Layer2,SignallingReceiver)
|
||||
|
||||
SS7MTP2::SS7MTP2(const NamedList& params, unsigned int status)
|
||||
: SignallingDumpable(SignallingDumper::Mtp2),
|
||||
Mutex(true),
|
||||
: SignallingComponent(params.safe("SS7MTP2"),¶ms),
|
||||
SignallingDumpable(SignallingDumper::Mtp2),
|
||||
Mutex(true,"SS7MTP2"),
|
||||
m_status(status), m_lStatus(OutOfService), m_rStatus(OutOfAlignment),
|
||||
m_interval(0), m_resend(0), m_abort(0), m_fillTime(0), m_congestion(false),
|
||||
m_bsn(127), m_fsn(127), m_bib(true), m_fib(true),
|
||||
m_lastFsn(128), m_lastBsn(127), m_lastBib(true), m_errors(0),
|
||||
m_resendMs(250), m_abortMs(5000), m_fillIntervalMs(20), m_fillLink(true)
|
||||
{
|
||||
setName(params.getValue("debugname","mtp2"));
|
||||
#ifdef DEBUG
|
||||
if (debugAt(DebugAll)) {
|
||||
String tmp;
|
||||
params.dump(tmp,"\r\n ",'\'',true);
|
||||
Debug(this,DebugAll,"SS7MTP2::SS7MTP2(%p,%s) [%p]%s",
|
||||
¶ms,statusName(true),this,tmp.c_str());
|
||||
}
|
||||
#endif
|
||||
m_fillLink = params.getBoolValue("filllink",m_fillLink);
|
||||
setDumper(params.getValue("layer2dump"));
|
||||
}
|
||||
|
@ -244,6 +251,46 @@ bool SS7MTP2::operational() const
|
|||
return aligned() && !m_interval;
|
||||
}
|
||||
|
||||
bool SS7MTP2::initialize(const NamedList* config)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
String tmp;
|
||||
if (config && debugAt(DebugAll))
|
||||
config->dump(tmp,"\r\n ",'\'',true);
|
||||
Debug(this,DebugInfo,"SS7MTP2::initialize(%p) [%p]%s",config,this,tmp.c_str());
|
||||
#endif
|
||||
if (config)
|
||||
debugLevel(config->getIntValue("debuglevel_mtp2",
|
||||
config->getIntValue("debuglevel",-1)));
|
||||
if (config && !iface()) {
|
||||
NamedString* name = config->getParam("sig");
|
||||
if (!name)
|
||||
name = config->getParam("basename");
|
||||
if (name) {
|
||||
NamedPointer* ptr = YOBJECT(NamedPointer,name);
|
||||
NamedList* ifConfig = ptr ? YOBJECT(NamedList,ptr->userData()) : 0;
|
||||
NamedList params(name->c_str());
|
||||
params.addParam("basename",*name);
|
||||
params.addParam("protocol","ss7");
|
||||
if (ifConfig) {
|
||||
params.copyParams(*ifConfig);
|
||||
int rx = params.getIntValue("rxunderrun");
|
||||
if ((rx > 0) && (rx < 25))
|
||||
params.setParam("rxunderrun","25");
|
||||
}
|
||||
else
|
||||
ifConfig = ¶ms;
|
||||
SignallingInterface* ifc = YSIGCREATE(SignallingInterface,¶ms);
|
||||
if (!ifc)
|
||||
return false;
|
||||
SignallingReceiver::attach(ifc);
|
||||
if (!ifc->initialize(ifConfig))
|
||||
TelEngine::destruct(SignallingReceiver::attach(0));
|
||||
}
|
||||
}
|
||||
return iface() && control(Resume,const_cast<NamedList*>(config));
|
||||
}
|
||||
|
||||
bool SS7MTP2::control(Operation oper, NamedList* params)
|
||||
{
|
||||
switch (oper) {
|
||||
|
|
|
@ -336,31 +336,49 @@ void SS7Layer3::printRoutes()
|
|||
Debug(this,DebugAll,"No %s [%p]",router?"routes":"destinations",this);
|
||||
}
|
||||
|
||||
|
||||
SS7MTP3::SS7MTP3(const NamedList& params)
|
||||
: SignallingDumpable(SignallingDumper::Mtp3),
|
||||
Mutex(true),
|
||||
: SignallingComponent(params.safe("SS7MTP3"),¶ms),
|
||||
SignallingDumpable(SignallingDumper::Mtp3),
|
||||
Mutex(true,"SS7MTP3"),
|
||||
m_total(0), m_active(0)
|
||||
{
|
||||
setName(params.getValue("debugname","mtp3"));
|
||||
#ifdef DEBUG
|
||||
if (debugAt(DebugAll)) {
|
||||
String tmp;
|
||||
params.dump(tmp,"\r\n ",'\'',true);
|
||||
Debug(this,DebugAll,"SS7MTP3::SS7MTP3(%p) [%p]%s",
|
||||
¶ms,this,tmp.c_str());
|
||||
}
|
||||
#endif
|
||||
// Set point code type for each network indicator
|
||||
static const unsigned char ni[4] = { SS7MSU::International,
|
||||
SS7MSU::SpareInternational, SS7MSU::National, SS7MSU::ReservedNational };
|
||||
String stype = params.getValue("netind2pctype");
|
||||
ObjList* obj = stype.split(',',false);
|
||||
int level = DebugAll;
|
||||
unsigned char ni[4] = {SS7MSU::International,SS7MSU::SpareInternational,
|
||||
SS7MSU::National,SS7MSU::ReservedNational};
|
||||
ObjList* o = obj->skipNull();
|
||||
for (unsigned int i = 0; i < 4; i++) {
|
||||
String* s = 0;
|
||||
if (o) {
|
||||
s = static_cast<String*>(o->get());
|
||||
o = o->skipNext();
|
||||
if (stype.find(',') >= 0) {
|
||||
ObjList* obj = stype.split(',',false);
|
||||
ObjList* o = obj->skipNull();
|
||||
for (unsigned int i = 0; i < 4; i++) {
|
||||
String* s = 0;
|
||||
if (o) {
|
||||
s = static_cast<String*>(o->get());
|
||||
o = o->skipNext();
|
||||
}
|
||||
SS7PointCode::Type type = SS7PointCode::lookup(s?s->c_str():0);
|
||||
if (type == SS7PointCode::Other)
|
||||
level = DebugNote;
|
||||
setType(type,ni[i]);
|
||||
}
|
||||
SS7PointCode::Type type = SS7PointCode::lookup(s?s->c_str():0);
|
||||
TelEngine::destruct(obj);
|
||||
}
|
||||
else {
|
||||
SS7PointCode::Type type = SS7PointCode::lookup(stype.c_str());
|
||||
if (type == SS7PointCode::Other)
|
||||
level = DebugNote;
|
||||
setType(type,ni[i]);
|
||||
for (unsigned int i = 0; i < 4; i++)
|
||||
setType(type,ni[i]);
|
||||
}
|
||||
TelEngine::destruct(obj);
|
||||
Debug(this,level,"Point code types are '%s' [%p]",stype.safe(),this);
|
||||
|
||||
buildRoutes(params);
|
||||
|
@ -461,6 +479,53 @@ void SS7MTP3::detach(SS7Layer2* link)
|
|||
}
|
||||
}
|
||||
|
||||
// Configure and initialize MTP3 and its links
|
||||
bool SS7MTP3::initialize(const NamedList* config)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
String tmp;
|
||||
if (config && debugAt(DebugAll))
|
||||
config->dump(tmp,"\r\n ",'\'',true);
|
||||
Debug(this,DebugInfo,"SS7MTP3::initialize(%p) [%p]%s",config,this,tmp.c_str());
|
||||
#endif
|
||||
if (config)
|
||||
debugLevel(config->getIntValue("debuglevel_mtp3",
|
||||
config->getIntValue("debuglevel",-1)));
|
||||
countLinks();
|
||||
if (config && (0 == m_total)) {
|
||||
unsigned int n = config->length();
|
||||
for (unsigned int i = 0; i < n; i++) {
|
||||
NamedString* param = config->getParam(i);
|
||||
if (!(param && param->name() == "link"))
|
||||
continue;
|
||||
NamedPointer* ptr = YOBJECT(NamedPointer,param);
|
||||
NamedList* linkConfig = ptr ? YOBJECT(NamedList,ptr->userData()) : 0;
|
||||
NamedList params(param->c_str());
|
||||
params.addParam("basename",*param);
|
||||
if (linkConfig)
|
||||
params.copyParams(*linkConfig);
|
||||
else
|
||||
linkConfig = ¶ms;
|
||||
SS7Layer2* link = YSIGCREATE(SS7Layer2,¶ms);
|
||||
if (!link)
|
||||
continue;
|
||||
attach(link);
|
||||
if (!link->initialize(linkConfig)) {
|
||||
detach(link);
|
||||
TelEngine::destruct(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (engine() && !user()) {
|
||||
NamedList params("ss7router");
|
||||
if (config)
|
||||
static_cast<String&>(params) = config->getValue("router",params);
|
||||
if (params.toBoolean(true))
|
||||
SS7Layer3::attach(YOBJECT(SS7Router,engine()->build("SS7Router",params,true)));
|
||||
}
|
||||
return 0 != m_total;
|
||||
}
|
||||
|
||||
// Detach all links and user. Destroys the object, disposes the memory
|
||||
void SS7MTP3::destroyed()
|
||||
{
|
||||
|
|
|
@ -29,10 +29,9 @@
|
|||
using namespace TelEngine;
|
||||
|
||||
SS7Layer4::SS7Layer4()
|
||||
: m_l3Mutex(true),
|
||||
m_layer3(0)
|
||||
: SignallingComponent("SS7Layer4"),
|
||||
m_l3Mutex(true,"SS7Layer4::layer3"), m_layer3(0)
|
||||
{
|
||||
setName("ss7l4");
|
||||
}
|
||||
|
||||
void SS7Layer4::attach(SS7Layer3* network)
|
||||
|
@ -59,11 +58,11 @@ void SS7Layer4::attach(SS7Layer3* network)
|
|||
Debug(this,DebugAll,"Attached network/router (%p,'%s') [%p]",
|
||||
network,network->toString().safe(),this);
|
||||
insert(network);
|
||||
if (network->getObject("SS7Router"))
|
||||
(static_cast<SS7Router*>(network))->attach(this);
|
||||
SS7Router* router = YOBJECT(SS7Router,network);
|
||||
if (router)
|
||||
router->attach(this);
|
||||
else
|
||||
network->attach(this);
|
||||
}
|
||||
|
||||
|
||||
/* vi: set ts=8 sw=4 sts=4 noet: */
|
||||
|
|
|
@ -52,7 +52,7 @@ int main()
|
|||
NamedList ifdefs("WpInterface");
|
||||
ifdefs.addParam("card","wanpipe1");
|
||||
ifdefs.addParam("device","w1g1");
|
||||
SignallingInterface* iface = static_cast<SignallingInterface*>(SignallingFactory::build(ifdefs,&ifdefs));
|
||||
SignallingInterface* iface = YSIGCREATE(SignallingInterface,&ifdefs);
|
||||
if (iface) {
|
||||
link->SignallingReceiver::attach(iface);
|
||||
iface->control(SignallingInterface::Enable);
|
||||
|
|
|
@ -46,11 +46,19 @@ static const char* s_linkSideCpe = "CPE";
|
|||
#define Q921_TEI_BROADCAST 127 // TEI value for broadcast and management procedures
|
||||
#define Q921_SAPI_MANAGEMENT 63 // SAPI value for management procedures
|
||||
|
||||
inline const char* linkSide(bool net)
|
||||
static inline const char* linkSide(bool net)
|
||||
{
|
||||
return net ? s_linkSideNet : s_linkSideCpe;
|
||||
}
|
||||
|
||||
static inline void fixParams(NamedList& params, const NamedList& config)
|
||||
{
|
||||
params.copyParams(config);
|
||||
int rx = params.getIntValue("rxunderrun");
|
||||
if ((rx > 0) && (rx < 2500))
|
||||
params.setParam("rxunderrun","2500");
|
||||
}
|
||||
|
||||
// Drop frame reasons
|
||||
static const char* s_noState = "Not allowed in this state";
|
||||
|
||||
|
@ -101,7 +109,7 @@ public:
|
|||
|
||||
// Constructor. Set data members. Print them
|
||||
ISDNQ921::ISDNQ921(const NamedList& params, const char* name, ISDNQ921Management* mgmt, u_int8_t tei)
|
||||
: SignallingComponent(name),
|
||||
: SignallingComponent(name,¶ms),
|
||||
ISDNLayer2(params,name,tei),
|
||||
SignallingReceiver(name),
|
||||
SignallingDumpable(SignallingDumper::Q921,network()),
|
||||
|
@ -131,8 +139,6 @@ ISDNQ921::ISDNQ921(const NamedList& params, const char* name, ISDNQ921Management
|
|||
{
|
||||
if (mgmt && network())
|
||||
autoRestart(false);
|
||||
if (!mgmt)
|
||||
setName(params.getValue("debugname",name));
|
||||
m_retransTimer.interval(params,"t200",1000,1000,false);
|
||||
m_idleTimer.interval(params,"t203",2000,10000,false);
|
||||
// Adjust idle timeout to data link side
|
||||
|
@ -145,6 +151,12 @@ ISDNQ921::ISDNQ921(const NamedList& params, const char* name, ISDNQ921Management
|
|||
if (debugAt(DebugInfo)) {
|
||||
String tmp;
|
||||
#ifdef DEBUG
|
||||
if (debugAt(DebugAll)) {
|
||||
params.dump(tmp,"\r\n ",'\'',true);
|
||||
Debug(this,DebugAll,"ISDNQ921::ISDNQ921(%p,'%s',%p,%u) [%p]%s",
|
||||
¶ms,name,mgmt,tei,this,tmp.c_str());
|
||||
tmp.clear();
|
||||
}
|
||||
tmp << " SAPI/TEI=" << (unsigned int)localSapi() << "/" << (unsigned int)localTei();
|
||||
tmp << " auto-restart=" << String::boolText(autoRestart());
|
||||
tmp << " max-user-data=" << (unsigned int)maxUserData();
|
||||
|
@ -164,7 +176,7 @@ ISDNQ921::~ISDNQ921()
|
|||
{
|
||||
Lock lock(l2Mutex());
|
||||
ISDNLayer2::attach((ISDNLayer3*)0);
|
||||
SignallingReceiver::attach(0);
|
||||
TelEngine::destruct(SignallingReceiver::attach(0));
|
||||
cleanup();
|
||||
DDebug(this,DebugAll,
|
||||
"ISDN Data Link destroyed. Frames: sent=%u (failed=%u) recv=%u rejected=%u dropped=%u. HW errors=%u [%p]",
|
||||
|
@ -173,6 +185,49 @@ ISDNQ921::~ISDNQ921()
|
|||
(unsigned int)m_rxDroppedFrames,(unsigned int)m_hwErrors,this);
|
||||
}
|
||||
|
||||
// Initialize layer, attach interface if not managed
|
||||
bool ISDNQ921::initialize(const NamedList* config)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
String tmp;
|
||||
if (config && debugAt(DebugAll))
|
||||
config->dump(tmp,"\r\n ",'\'',true);
|
||||
Debug(this,DebugInfo,"ISDNQ921::initialize(%p) [%p]%s",config,this,tmp.c_str());
|
||||
#endif
|
||||
if (config) {
|
||||
debugLevel(config->getIntValue("debuglevel_q921",
|
||||
config->getIntValue("debuglevel",-1)));
|
||||
setDebug(config->getBoolValue("print-frames",false),
|
||||
config->getBoolValue("extended-debug",false));
|
||||
}
|
||||
if (config && !m_management && !iface()) {
|
||||
NamedString* name = config->getParam("sig");
|
||||
if (!name)
|
||||
name = config->getParam("basename");
|
||||
if (name) {
|
||||
NamedPointer* ptr = YOBJECT(NamedPointer,name);
|
||||
NamedList* ifConfig = ptr ? YOBJECT(NamedList,ptr->userData()) : 0;
|
||||
NamedList params(*name + "/D");
|
||||
params.addParam("basename",*name);
|
||||
if (ifConfig)
|
||||
fixParams(params,*ifConfig);
|
||||
else
|
||||
ifConfig = ¶ms;
|
||||
SignallingInterface* ifc = YSIGCREATE(SignallingInterface,¶ms);
|
||||
if (!ifc)
|
||||
return false;
|
||||
SignallingReceiver::attach(ifc);
|
||||
if (ifc->initialize(ifConfig)) {
|
||||
SignallingReceiver::control(SignallingInterface::Enable);
|
||||
multipleFrame(0,true,false);
|
||||
}
|
||||
else
|
||||
TelEngine::destruct(SignallingReceiver::attach(0));
|
||||
}
|
||||
}
|
||||
return m_management || iface();
|
||||
}
|
||||
|
||||
// Set or release 'multiple frame acknowledged' mode
|
||||
bool ISDNQ921::multipleFrame(u_int8_t tei, bool establish, bool force)
|
||||
{
|
||||
|
@ -256,8 +311,6 @@ void ISDNQ921::cleanup()
|
|||
changeState(Released,"cleanup");
|
||||
}
|
||||
|
||||
YCLASSIMP2(ISDNQ921,ISDNLayer2,SignallingReceiver)
|
||||
|
||||
// Method called periodically to check timeouts
|
||||
// Re-sync with remote peer if necessary
|
||||
void ISDNQ921::timerTick(const Time& when)
|
||||
|
@ -766,7 +819,7 @@ bool ISDNQ921::acceptFrame(ISDNFrame* frame, bool& reject)
|
|||
!frame->command()) ||
|
||||
((frame->type() == ISDNFrame::UA || frame->type() == ISDNFrame::DM) &&
|
||||
frame->command())) {
|
||||
Debug(this,DebugGoOn,
|
||||
Debug(this,DebugMild,
|
||||
"Received '%s': The remote peer has the same data link side type",
|
||||
frame->name());
|
||||
frame->m_error = ISDNFrame::ErrInvalidCR;
|
||||
|
@ -970,13 +1023,21 @@ void ISDNQ921::timer(bool start, bool t203, u_int64_t time)
|
|||
*/
|
||||
// Constructor
|
||||
ISDNQ921Management::ISDNQ921Management(const NamedList& params, const char* name, bool net)
|
||||
: ISDNLayer2(params,name),
|
||||
: SignallingComponent(name,¶ms),
|
||||
ISDNLayer2(params,name),
|
||||
SignallingReceiver(name),
|
||||
SignallingDumpable(SignallingDumper::Q921,network()),
|
||||
m_teiManTimer(0), m_teiTimer(0)
|
||||
{
|
||||
String baseName = params.getValue("debugname",name);
|
||||
setName(baseName);
|
||||
#ifdef DEBUG
|
||||
if (debugAt(DebugAll)) {
|
||||
String tmp;
|
||||
params.dump(tmp,"\r\n ",'\'',true);
|
||||
Debug(this,DebugAll,"ISDNQ921Management::ISDNQ921Management(%p,'%s',%s) [%p]%s",
|
||||
¶ms,name,String::boolText(net),this,tmp.c_str());
|
||||
}
|
||||
#endif
|
||||
String baseName = toString();
|
||||
m_network = net;
|
||||
m_teiManTimer.interval(params,"t202",2500,2600,false);
|
||||
m_teiTimer.interval(params,"t201",1000,5000,false);
|
||||
|
@ -990,7 +1051,9 @@ ISDNQ921Management::ISDNQ921Management(const NamedList& params, const char* name
|
|||
for (int i = 0; i < 127; i++) {
|
||||
if (network() || (i == 0)) {
|
||||
String qName = baseName;
|
||||
if (set0 || (i != 0))
|
||||
if (!network())
|
||||
qName << "-CPE";
|
||||
else if (set0 || (i != 0))
|
||||
qName << "-" << i;
|
||||
m_layer2[i] = new ISDNQ921(params,qName,this,i);
|
||||
m_layer2[i]->ISDNLayer2::attach(this);
|
||||
|
@ -1008,12 +1071,47 @@ ISDNQ921Management::~ISDNQ921Management()
|
|||
{
|
||||
Lock lock(l2Mutex());
|
||||
ISDNLayer2::attach((ISDNLayer3*)0);
|
||||
SignallingReceiver::attach(0);
|
||||
TelEngine::destruct(SignallingReceiver::attach(0));
|
||||
for (int i = 0; i < 127; i++)
|
||||
TelEngine::destruct(m_layer2[i]);
|
||||
}
|
||||
|
||||
YCLASSIMP3(ISDNQ921Management,ISDNLayer2,ISDNLayer3,SignallingReceiver)
|
||||
bool ISDNQ921Management::initialize(const NamedList* config)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
String tmp;
|
||||
if (config && debugAt(DebugAll))
|
||||
config->dump(tmp,"\r\n ",'\'',true);
|
||||
Debug(this,DebugInfo,"ISDNQ921Management::initialize(%p) [%p]%s",config,this,tmp.c_str());
|
||||
#endif
|
||||
if (config)
|
||||
debugLevel(config->getIntValue("debuglevel_q921mgmt",
|
||||
config->getIntValue("debuglevel",-1)));
|
||||
if (config && !iface()) {
|
||||
NamedString* name = config->getParam("sig");
|
||||
if (!name)
|
||||
name = config->getParam("basename");
|
||||
if (name) {
|
||||
NamedPointer* ptr = YOBJECT(NamedPointer,name);
|
||||
NamedList* ifConfig = ptr ? YOBJECT(NamedList,ptr->userData()) : 0;
|
||||
NamedList params(*name + "/D");
|
||||
params.addParam("basename",*name);
|
||||
if (ifConfig)
|
||||
fixParams(params,*ifConfig);
|
||||
else
|
||||
ifConfig = ¶ms;
|
||||
SignallingInterface* ifc = YSIGCREATE(SignallingInterface,¶ms);
|
||||
if (!ifc)
|
||||
return false;
|
||||
SignallingReceiver::attach(ifc);
|
||||
if (ifc->initialize(ifConfig))
|
||||
SignallingReceiver::control(SignallingInterface::Enable);
|
||||
else
|
||||
TelEngine::destruct(SignallingReceiver::attach(0));
|
||||
}
|
||||
}
|
||||
return 0 != iface();
|
||||
}
|
||||
|
||||
void ISDNQ921Management::engine(SignallingEngine* eng)
|
||||
{
|
||||
|
@ -1387,7 +1485,8 @@ void ISDNQ921Management::processTeiVerify(u_int8_t ai, bool pf)
|
|||
*/
|
||||
// Constructor. Set data members. Print them
|
||||
ISDNQ921Passive::ISDNQ921Passive(const NamedList& params, const char* name)
|
||||
: ISDNLayer2(params,name),
|
||||
: SignallingComponent(name,¶ms),
|
||||
ISDNLayer2(params,name),
|
||||
SignallingReceiver(name),
|
||||
SignallingDumpable(SignallingDumper::Q921,network()),
|
||||
m_checkLinkSide(false),
|
||||
|
@ -1401,7 +1500,14 @@ ISDNQ921Passive::ISDNQ921Passive(const NamedList& params, const char* name)
|
|||
m_extendedDebug(false),
|
||||
m_errorReceive(false)
|
||||
{
|
||||
setName(params.getValue("debugname",name));
|
||||
#ifdef DEBUG
|
||||
if (debugAt(DebugAll)) {
|
||||
String tmp;
|
||||
params.dump(tmp,"\r\n ",'\'',true);
|
||||
Debug(this,DebugAll,"ISDNQ921Passive::ISDNQ921Passive(%p,'%s') [%p]%s",
|
||||
¶ms,name,this,tmp.c_str());
|
||||
}
|
||||
#endif
|
||||
m_idleTimer.interval(params,"idletimeout",4000,30000,false);
|
||||
m_checkLinkSide = detectType();
|
||||
setDebug(params.getBoolValue("print-frames",false),
|
||||
|
@ -1421,7 +1527,7 @@ ISDNQ921Passive::~ISDNQ921Passive()
|
|||
{
|
||||
Lock lock(l2Mutex());
|
||||
ISDNLayer2::attach(0);
|
||||
SignallingReceiver::attach(0);
|
||||
TelEngine::destruct(SignallingReceiver::attach(0));
|
||||
cleanup();
|
||||
DDebug(this,DebugAll,
|
||||
"ISDN Passive Data Link destroyed. Frames: recv=%u rejected=%u dropped=%u. HW errors=%u [%p]",
|
||||
|
@ -1429,6 +1535,47 @@ ISDNQ921Passive::~ISDNQ921Passive()
|
|||
(unsigned int)m_rxDroppedFrames,(unsigned int)m_hwErrors,this);
|
||||
}
|
||||
|
||||
bool ISDNQ921Passive::initialize(const NamedList* config)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
String tmp;
|
||||
if (config && debugAt(DebugAll))
|
||||
config->dump(tmp,"\r\n ",'\'',true);
|
||||
Debug(this,DebugInfo,"ISDNQ921Passive::initialize(%p) [%p]%s",config,this,tmp.c_str());
|
||||
#endif
|
||||
if (config) {
|
||||
debugLevel(config->getIntValue("debuglevel_q921",
|
||||
config->getIntValue("debuglevel",-1)));
|
||||
setDebug(config->getBoolValue("print-frames",false),
|
||||
config->getBoolValue("extended-debug",false));
|
||||
}
|
||||
if (config && !iface()) {
|
||||
NamedString* name = config->getParam("sig");
|
||||
if (!name)
|
||||
name = config->getParam("basename");
|
||||
if (name) {
|
||||
NamedPointer* ptr = YOBJECT(NamedPointer,name);
|
||||
NamedList* ifConfig = ptr ? YOBJECT(NamedList,ptr->userData()) : 0;
|
||||
NamedList params(*name + "/D");
|
||||
params.addParam("basename",*name);
|
||||
params.addParam("readonly",String::boolText(true));
|
||||
if (ifConfig)
|
||||
fixParams(params,*ifConfig);
|
||||
else
|
||||
ifConfig = ¶ms;
|
||||
SignallingInterface* ifc = YSIGCREATE(SignallingInterface,¶ms);
|
||||
if (!ifc)
|
||||
return false;
|
||||
SignallingReceiver::attach(ifc);
|
||||
if (ifc->initialize(ifConfig))
|
||||
SignallingReceiver::control(SignallingInterface::Enable);
|
||||
else
|
||||
TelEngine::destruct(SignallingReceiver::attach(0));
|
||||
}
|
||||
}
|
||||
return 0 != iface();
|
||||
}
|
||||
|
||||
// Reset data
|
||||
void ISDNQ921Passive::cleanup()
|
||||
{
|
||||
|
@ -1436,8 +1583,6 @@ void ISDNQ921Passive::cleanup()
|
|||
m_idleTimer.start();
|
||||
}
|
||||
|
||||
YCLASSIMP2(ISDNQ921Passive,ISDNLayer2,SignallingReceiver)
|
||||
|
||||
// Called periodically by the engine to check timeouts
|
||||
// Check idle timer. Notify upper layer on timeout
|
||||
void ISDNQ921Passive::timerTick(const Time& when)
|
||||
|
@ -1546,7 +1691,7 @@ bool ISDNQ921Passive::acceptFrame(ISDNFrame* frame, bool& cmd, bool& value)
|
|||
changeType();
|
||||
}
|
||||
else {
|
||||
Debug(this,DebugGoOn,
|
||||
Debug(this,DebugMild,
|
||||
"Received '%s': The remote peer has the same data link side type",
|
||||
frame->name());
|
||||
return dropFrame(frame,ISDNFrame::typeName(ISDNFrame::ErrInvalidCR));
|
||||
|
@ -1595,10 +1740,10 @@ TokenDict ISDNLayer2::m_states[] = {
|
|||
};
|
||||
|
||||
ISDNLayer2::ISDNLayer2(const NamedList& params, const char* name, u_int8_t tei)
|
||||
: SignallingComponent(name),
|
||||
: SignallingComponent(name,¶ms),
|
||||
m_layer3(0),
|
||||
m_layerMutex(true),
|
||||
m_layer3Mutex(true),
|
||||
m_layerMutex(true,"ISDNLayer2::layer"),
|
||||
m_layer3Mutex(true,"ISDNLayer2::layer3"),
|
||||
m_state(Released),
|
||||
m_network(false),
|
||||
m_detectType(false),
|
||||
|
@ -1643,16 +1788,14 @@ void ISDNLayer2::attach(ISDNLayer3* layer3)
|
|||
m_layer3 = layer3;
|
||||
lock.drop();
|
||||
if (tmp) {
|
||||
const char* name = 0;
|
||||
if (engine() && engine()->find(tmp)) {
|
||||
name = tmp->toString().safe();
|
||||
if (engine() && engine()->find(tmp))
|
||||
tmp->attach(0);
|
||||
}
|
||||
DDebug(this,DebugAll,"Detached L3 (%p,'%s') [%p]",tmp,name,this);
|
||||
Debug(this,DebugAll,"Detached L3 (%p,'%s') [%p]",
|
||||
tmp,tmp->toString().safe(),this);
|
||||
}
|
||||
if (!layer3)
|
||||
return;
|
||||
DDebug(this,DebugAll,"Attached L3 (%p,'%s') [%p]",layer3,layer3->toString().safe(),this);
|
||||
Debug(this,DebugAll,"Attached L3 (%p,'%s') [%p]",layer3,layer3->toString().safe(),this);
|
||||
insert(layer3);
|
||||
layer3->attach(this);
|
||||
}
|
||||
|
|
|
@ -735,7 +735,7 @@ ISDNQ931Call::ISDNQ931Call(ISDNQ931* controller, bool outgoing,
|
|||
m_data.m_reason = "temporary-failure";
|
||||
return;
|
||||
}
|
||||
m_net = q931() && q931()->m_q921 && q931()->m_q921->network();
|
||||
m_net = q931() && q931()->network();
|
||||
// Init timers
|
||||
q931()->setInterval(m_discTimer,305);
|
||||
q931()->setInterval(m_relTimer,308);
|
||||
|
@ -759,7 +759,7 @@ ISDNQ931Call::~ISDNQ931Call()
|
|||
// Set terminate flags and reason
|
||||
void ISDNQ931Call::setTerminate(bool destroy, const char* reason)
|
||||
{
|
||||
Lock lock(m_callMutex);
|
||||
Lock mylock(this);
|
||||
if (m_destroyed)
|
||||
return;
|
||||
if (state() == CallAbort)
|
||||
|
@ -780,7 +780,7 @@ bool ISDNQ931Call::sendEvent(SignallingEvent* event)
|
|||
{
|
||||
if (!event)
|
||||
return false;
|
||||
Lock lock(m_callMutex);
|
||||
Lock mylock(this);
|
||||
DDebug(q931(),DebugAll,"Call(%u,%u). sendEvent(%s) state=%s [%p]",
|
||||
Q931_CALL_ID,event->name(),stateName(state()),this);
|
||||
if (m_terminate || state() == CallAbort) {
|
||||
|
@ -855,7 +855,7 @@ bool ISDNQ931Call::sendEvent(SignallingEvent* event)
|
|||
// Get events from reserved circuit when no call event
|
||||
SignallingEvent* ISDNQ931Call::getEvent(const Time& when)
|
||||
{
|
||||
Lock lock(m_callMutex);
|
||||
Lock mylock(this);
|
||||
// Check for last event or destroyed/aborting
|
||||
if (m_lastEvent || m_destroyed || state() == CallAbort)
|
||||
return 0;
|
||||
|
@ -951,7 +951,7 @@ void* ISDNQ931Call::getObject(const String& name) const
|
|||
// Set termination flag. Send status if link is up
|
||||
void ISDNQ931Call::dataLinkState(bool up)
|
||||
{
|
||||
Lock lock(m_callMutex);
|
||||
Lock mylock(this);
|
||||
// Q.931 5.8.9. Terminate if not up and not in the active state
|
||||
if (!up) {
|
||||
if (state() != ISDNQ931Call::Active)
|
||||
|
@ -1736,7 +1736,7 @@ bool ISDNQ931Call::sendSetupAck()
|
|||
|
||||
SignallingEvent* ISDNQ931Call::releaseComplete(const char* reason, const char* diag)
|
||||
{
|
||||
Lock lock(m_callMutex);
|
||||
Lock mylock(this);
|
||||
if (m_destroyed)
|
||||
return 0;
|
||||
if (reason)
|
||||
|
@ -1930,7 +1930,7 @@ ISDNQ931CallMonitor::~ISDNQ931CallMonitor()
|
|||
// Get an event from this monitor
|
||||
SignallingEvent* ISDNQ931CallMonitor::getEvent(const Time& when)
|
||||
{
|
||||
Lock lock(m_callMutex);
|
||||
Lock mylock(this);
|
||||
// Check for last event or aborting
|
||||
if (m_lastEvent || state() == CallAbort)
|
||||
return 0;
|
||||
|
@ -1982,7 +1982,7 @@ SignallingEvent* ISDNQ931CallMonitor::getEvent(const Time& when)
|
|||
// Set termination flag
|
||||
void ISDNQ931CallMonitor::setTerminate(const char* reason)
|
||||
{
|
||||
Lock lock(m_callMutex);
|
||||
Lock mylock(this);
|
||||
if (state() == CallAbort)
|
||||
changeState(Null);
|
||||
// Check terminate & destroy flags
|
||||
|
@ -2136,7 +2136,7 @@ SignallingEvent* ISDNQ931CallMonitor::processMsgInfo(ISDNQ931Message* msg)
|
|||
// Release monitor
|
||||
SignallingEvent* ISDNQ931CallMonitor::releaseComplete(const char* reason)
|
||||
{
|
||||
Lock lock(m_callMutex);
|
||||
Lock mylock(this);
|
||||
if (state() == Null)
|
||||
return 0;
|
||||
if (reason)
|
||||
|
@ -2316,15 +2316,14 @@ TokenDict ISDNQ931::s_swType[] = {
|
|||
{0,0}
|
||||
};
|
||||
|
||||
YCLASSIMP(ISDNQ931,ISDNLayer3)
|
||||
|
||||
ISDNQ931::ISDNQ931(const NamedList& params, const char* name)
|
||||
: SignallingComponent(name),
|
||||
: SignallingComponent(name,¶ms),
|
||||
SignallingCallControl(params,"isdn."),
|
||||
SignallingDumpable(SignallingDumper::Q931),
|
||||
ISDNLayer3(name),
|
||||
m_q921(0),
|
||||
m_q921Up(false),
|
||||
m_networkHint(true),
|
||||
m_primaryRate(true),
|
||||
m_transferModeCircuit(true),
|
||||
m_callRef(1),
|
||||
|
@ -2348,9 +2347,18 @@ ISDNQ931::ISDNQ931(const NamedList& params, const char* name)
|
|||
m_flagQ921Down(false),
|
||||
m_flagQ921Invalid(false)
|
||||
{
|
||||
setName(params.getValue("debugname",name));
|
||||
#ifdef DEBUG
|
||||
if (debugAt(DebugAll)) {
|
||||
String tmp;
|
||||
params.dump(tmp,"\r\n ",'\'',true);
|
||||
Debug(this,DebugAll,"ISDNQ931::ISDNQ931(%p,'%s') [%p]%s",
|
||||
¶ms,name,this,tmp.c_str());
|
||||
}
|
||||
#endif
|
||||
m_parserData.m_dbg = this;
|
||||
m_callRefLen = params.getIntValue("callreflen",2);
|
||||
m_networkHint = params.getBoolValue("network",m_networkHint);
|
||||
m_data.m_bri = !(m_primaryRate = params.getBoolValue("primary",m_primaryRate));
|
||||
m_callRefLen = params.getIntValue("callreflen",m_primaryRate ? 2 : 1);
|
||||
if (m_callRefLen < 1 || m_callRefLen > 4)
|
||||
m_callRefLen = 2;
|
||||
// Set mask. Bit 7 of the first byte of the message header it's used for initiator flag
|
||||
|
@ -2383,9 +2391,9 @@ ISDNQ931::ISDNQ931(const NamedList& params, const char* name)
|
|||
setDebug(params.getBoolValue("print-messages",false),
|
||||
params.getBoolValue("extended-debug",false));
|
||||
if (debugAt(DebugInfo)) {
|
||||
String s;
|
||||
String s(network() ? "NET" : "CPE");
|
||||
#ifdef DEBUG
|
||||
s << "type=" << lookup(m_parserData.m_flags,s_swType,"Custom");
|
||||
s << " type=" << lookup(m_parserData.m_flags,s_swType,"Custom");
|
||||
String t;
|
||||
for (TokenDict* p = s_flags; p->token; p++)
|
||||
if (m_parserData.flag(p->value))
|
||||
|
@ -2406,7 +2414,7 @@ ISDNQ931::ISDNQ931(const NamedList& params, const char* name)
|
|||
s << " segmentation=" << String::boolText(m_parserData.m_allowSegment);
|
||||
s << " max-segments=" << (unsigned int)m_parserData.m_maxSegments;
|
||||
#else
|
||||
s << "type=" << params.getValue("switchtype");
|
||||
s << " type=" << params.getValue("switchtype");
|
||||
s << " pri=" << String::boolText(m_primaryRate);
|
||||
s << " format=" << m_format;
|
||||
s << " channelsync=" << String::boolText(0 != m_syncGroupTimer.interval());
|
||||
|
@ -2423,10 +2431,54 @@ ISDNQ931::~ISDNQ931()
|
|||
cleanup();
|
||||
m_calls.clear();
|
||||
}
|
||||
attach((ISDNLayer2*)0);
|
||||
TelEngine::destruct(attach((ISDNLayer2*)0));
|
||||
TelEngine::destruct(SignallingCallControl::attach(0));
|
||||
DDebug(this,DebugAll,"ISDN Call Controller destroyed [%p]",this);
|
||||
}
|
||||
|
||||
// Initialize Q.931 and attach a layer 2
|
||||
bool ISDNQ931::initialize(const NamedList* config)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
String tmp;
|
||||
if (config && debugAt(DebugAll))
|
||||
config->dump(tmp,"\r\n ",'\'',true);
|
||||
Debug(this,DebugInfo,"ISDNQ931::initialize(%p) [%p]%s",config,this,tmp.c_str());
|
||||
#endif
|
||||
if (config) {
|
||||
debugLevel(config->getIntValue("debuglevel_q931",
|
||||
config->getIntValue("debuglevel",-1)));
|
||||
setDebug(config->getBoolValue("print-messages",false),
|
||||
config->getBoolValue("extended-debug",false));
|
||||
}
|
||||
if (config && !layer2()) {
|
||||
const String* name = config->getParam("sig");
|
||||
if (!name)
|
||||
name = config;
|
||||
if (!TelEngine::null(name)) {
|
||||
NamedPointer* ptr = YOBJECT(NamedPointer,name);
|
||||
NamedList* linkConfig = ptr ? YOBJECT(NamedList,ptr->userData()) : 0;
|
||||
NamedList params(*name + "/Q921");
|
||||
params.addParam("basename",*name);
|
||||
params.addParam("primary",String::boolText(primaryRate()));
|
||||
params.addParam("network",String::boolText(network()));
|
||||
if (linkConfig)
|
||||
params.copyParams(*linkConfig);
|
||||
else
|
||||
linkConfig = ¶ms;
|
||||
ISDNLayer2* l2 = YSIGCREATE(ISDNLayer2,¶ms);
|
||||
if (!l2) {
|
||||
Debug(this,DebugWarn,"Could not create ISDN Layer 2 '%s' [%p]",name->c_str(),this);
|
||||
return false;
|
||||
}
|
||||
attach(l2);
|
||||
if (!l2->initialize(linkConfig))
|
||||
TelEngine::destruct(attach((ISDNLayer2*)0));
|
||||
}
|
||||
}
|
||||
return 0 != layer2();
|
||||
}
|
||||
|
||||
// Check if layer 2 may be up
|
||||
bool ISDNQ931::q921Up() const
|
||||
{
|
||||
|
@ -2435,7 +2487,7 @@ bool ISDNQ931::q921Up() const
|
|||
if (m_q921Up)
|
||||
return true;
|
||||
// Assume BRI NET is always up
|
||||
return !primaryRate() && m_q921->network();
|
||||
return !primaryRate() && network();
|
||||
}
|
||||
|
||||
// Send a message to layer 2
|
||||
|
@ -2620,7 +2672,7 @@ void ISDNQ931::receiveData(const DataBlock& data, u_int8_t tei, ISDNLayer2* laye
|
|||
}
|
||||
// Check if it is a new incoming call
|
||||
if (msg->initiator() && msg->type() == ISDNQ931Message::Setup) {
|
||||
if (!primaryRate() && m_cpeNumber && m_q921 && !m_q921->network()) {
|
||||
if (!primaryRate() && m_cpeNumber && !network()) {
|
||||
// We are a BRI CPE with a number - check the called party field
|
||||
ISDNQ931IE* ie = msg->getIE(ISDNQ931IE::CalledNo);
|
||||
if (ie) {
|
||||
|
@ -2654,11 +2706,11 @@ void ISDNQ931::receiveData(const DataBlock& data, u_int8_t tei, ISDNLayer2* laye
|
|||
|
||||
// Attach layer 2
|
||||
// Update some data from the attached object
|
||||
void ISDNQ931::attach(ISDNLayer2* q921)
|
||||
ISDNLayer2* ISDNQ931::attach(ISDNLayer2* q921)
|
||||
{
|
||||
Lock lock(l3Mutex());
|
||||
if (m_q921 == q921)
|
||||
return;
|
||||
return 0;
|
||||
cleanup(q921 ? "layer 2 attach" : "layer 2 detach");
|
||||
ISDNLayer2* tmp = m_q921;
|
||||
m_q921 = q921;
|
||||
|
@ -2704,20 +2756,25 @@ void ISDNQ931::attach(ISDNLayer2* q921)
|
|||
}
|
||||
lock.drop();
|
||||
if (tmp) {
|
||||
const char* name = 0;
|
||||
if (engine() && engine()->find(tmp)) {
|
||||
name = tmp->toString().safe();
|
||||
if (tmp->layer3() == this) {
|
||||
Debug(this,DebugAll,"Detaching L2 (%p,'%s') [%p]",
|
||||
tmp,tmp->toString().safe(),this);
|
||||
tmp->attach(0);
|
||||
}
|
||||
Debug(this,DebugAll,"Detached L2 (%p,'%s') [%p]",tmp,name,this);
|
||||
else {
|
||||
Debug(this,DebugNote,"Layer 2 (%p,'%s') was not attached to us [%p]",
|
||||
tmp,tmp->toString().safe(),this);
|
||||
tmp = 0;
|
||||
}
|
||||
}
|
||||
if (!q921)
|
||||
return;
|
||||
return tmp;
|
||||
Debug(this,DebugAll,"Attached L2 '%s' (%p,'%s') [%p]",
|
||||
(q921->network() ? "NET" : "CPE"),
|
||||
q921,q921->toString().safe(),this);
|
||||
insert(q921);
|
||||
q921->attach(this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// Make an outgoing call from a given message
|
||||
|
@ -3332,37 +3389,82 @@ bool ISDNQ931::sendRelease(bool release, u_int8_t callRefLen, u_int32_t callRef,
|
|||
* ISDNQ931Monitor
|
||||
*/
|
||||
ISDNQ931Monitor::ISDNQ931Monitor(const NamedList& params, const char* name)
|
||||
: SignallingCallControl(params,"isdn."),
|
||||
ISDNLayer3(name),
|
||||
m_q921Net(0),
|
||||
m_q921Cpe(0),
|
||||
m_cicNet(0),
|
||||
m_cicCpe(0),
|
||||
m_parserData(params),
|
||||
m_printMsg(true),
|
||||
m_extendedDebug(false)
|
||||
: SignallingComponent(name,¶ms),
|
||||
SignallingCallControl(params,"isdn."),
|
||||
ISDNLayer3(name),
|
||||
m_q921Net(0), m_q921Cpe(0), m_cicNet(0), m_cicCpe(0),
|
||||
m_parserData(params),
|
||||
m_printMsg(true), m_extendedDebug(false)
|
||||
{
|
||||
setName(params.getValue("debugname",name));
|
||||
#ifdef DEBUG
|
||||
if (debugAt(DebugAll)) {
|
||||
String tmp;
|
||||
params.dump(tmp,"\r\n ",'\'',true);
|
||||
Debug(this,DebugAll,"ISDNQ931Monitor::ISDNQ931Monitor(%p,'%s') [%p]%s",
|
||||
¶ms,name,this,tmp.c_str());
|
||||
}
|
||||
#endif
|
||||
// Set parser data. Accept maximum data length
|
||||
m_parserData.m_maxMsgLen = 0xffffffff;
|
||||
m_parserData.m_dbg = this;
|
||||
// Debug
|
||||
setDebug(params.getBoolValue("print-messages",true),
|
||||
params.getBoolValue("extended-debug",false));
|
||||
Debug(this,DebugAll,"ISDN Monitor created [%p]",this);
|
||||
}
|
||||
|
||||
ISDNQ931Monitor::~ISDNQ931Monitor()
|
||||
{
|
||||
terminateMonitor(0,0);
|
||||
attach((ISDNQ921Passive*)0,true);
|
||||
attach((ISDNQ921Passive*)0,false);
|
||||
attach((SignallingCircuitGroup*)0,true);
|
||||
attach((SignallingCircuitGroup*)0,false);
|
||||
TelEngine::destruct(attach((ISDNQ921Passive*)0,true));
|
||||
TelEngine::destruct(attach((ISDNQ921Passive*)0,false));
|
||||
TelEngine::destruct(attach((SignallingCircuitGroup*)0,true));
|
||||
TelEngine::destruct(attach((SignallingCircuitGroup*)0,false));
|
||||
m_calls.clear();
|
||||
DDebug(this,DebugAll,"ISDN Monitor destroyed [%p]",this);
|
||||
}
|
||||
|
||||
// Initialize the monitor and attach both passive layer 2
|
||||
bool ISDNQ931Monitor::initialize(const NamedList* config)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
String tmp;
|
||||
if (config && debugAt(DebugAll))
|
||||
config->dump(tmp,"\r\n ",'\'',true);
|
||||
Debug(this,DebugInfo,"ISDNQ931Monitor::initialize(%p) [%p]%s",config,this,tmp.c_str());
|
||||
#endif
|
||||
if (config) {
|
||||
debugLevel(config->getIntValue("debuglevel_q931",
|
||||
config->getIntValue("debuglevel",-1)));
|
||||
setDebug(config->getBoolValue("print-messages",false),
|
||||
config->getBoolValue("extended-debug",false));
|
||||
for (int i = 0; i <= 1; i++) {
|
||||
bool net = (0 == i);
|
||||
if (net && m_q921Net)
|
||||
continue;
|
||||
if (!net && m_q921Cpe)
|
||||
continue;
|
||||
NamedString* name = config->getParam(net ? "sig-net" : "sig-cpe");
|
||||
if (name) {
|
||||
NamedPointer* ptr = YOBJECT(NamedPointer,name);
|
||||
NamedList* linkConfig = ptr ? YOBJECT(NamedList,ptr->userData()) : 0;
|
||||
NamedList params(name->c_str());
|
||||
params.addParam("basename",*name);
|
||||
if (linkConfig)
|
||||
params.copyParams(*linkConfig);
|
||||
else
|
||||
linkConfig = ¶ms;
|
||||
ISDNQ921Passive* l2 = YSIGCREATE(ISDNQ921Passive,¶ms);
|
||||
if (!l2)
|
||||
return false;
|
||||
attach(l2,net);
|
||||
if (!l2->initialize(linkConfig))
|
||||
TelEngine::destruct(attach((ISDNQ921Passive*)0,net));
|
||||
}
|
||||
}
|
||||
}
|
||||
return m_q921Net && m_q921Cpe;
|
||||
}
|
||||
|
||||
// Notification from layer 2 of data link set/release command or response
|
||||
void ISDNQ931Monitor::dataLinkState(u_int8_t tei, bool cmd, bool value, ISDNLayer2* layer2)
|
||||
{
|
||||
|
@ -3446,64 +3548,64 @@ void ISDNQ931Monitor::receiveData(const DataBlock& data, u_int8_t tei, ISDNLayer
|
|||
}
|
||||
|
||||
// Attach ISDN Q.921 pasive transport that monitors one side of the link
|
||||
void ISDNQ931Monitor::attach(ISDNQ921Passive* q921, bool net)
|
||||
ISDNQ921Passive* ISDNQ931Monitor::attach(ISDNQ921Passive* q921, bool net)
|
||||
{
|
||||
Lock lock(l3Mutex());
|
||||
ISDNQ921Passive* which = net ? m_q921Net : m_q921Cpe;
|
||||
// Yes, this is a reference to a pointer
|
||||
ISDNQ921Passive*& which = net ? m_q921Net : m_q921Cpe;
|
||||
// Make no change if same transport
|
||||
if (which == q921)
|
||||
return;
|
||||
return 0;
|
||||
terminateMonitor(0,q921 ? "layer 2 attach" : "layer 2 detach");
|
||||
ISDNQ921Passive* tmp = which;
|
||||
if (net)
|
||||
m_q921Net = q921;
|
||||
else
|
||||
m_q921Cpe = q921;
|
||||
which = q921;
|
||||
lock.drop();
|
||||
const char* type = net ? "NET" : "CPE";
|
||||
if (tmp) {
|
||||
const char* name = 0;
|
||||
if (engine() && engine()->find(tmp)) {
|
||||
name = tmp->toString().safe();
|
||||
static_cast<ISDNLayer2*>(tmp)->attach((ISDNLayer3*)0);
|
||||
if (tmp->layer3() == this) {
|
||||
Debug(this,DebugAll,"Detaching L2 %s (%p,'%s') [%p]",
|
||||
type,tmp,tmp->toString().safe(),this);
|
||||
static_cast<ISDNLayer2*>(tmp)->attach(0);
|
||||
}
|
||||
else {
|
||||
Debug(this,DebugNote,"Layer 2 %s (%p,'%s') was not attached to us [%p]",
|
||||
type,tmp,tmp->toString().safe(),this);
|
||||
tmp = 0;
|
||||
}
|
||||
Debug(this,DebugAll,"Detached L2 %s (%p,'%s') [%p]",net?"NET":"CPE",tmp,name,this);
|
||||
}
|
||||
if (!q921)
|
||||
return;
|
||||
return tmp;
|
||||
Debug(this,DebugAll,"Attached L2 %s (%p,'%s') [%p]",
|
||||
net?"NET":"CPE",q921,q921->toString().safe(),this);
|
||||
type,q921,q921->toString().safe(),this);
|
||||
insert(q921);
|
||||
q921->ISDNLayer2::attach(this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// Attach a circuit group to this call controller
|
||||
void ISDNQ931Monitor::attach(SignallingCircuitGroup* circuits, bool net)
|
||||
SignallingCircuitGroup* ISDNQ931Monitor::attach(SignallingCircuitGroup* circuits, bool net)
|
||||
{
|
||||
Lock lock(l3Mutex());
|
||||
// Yes, this is a reference to a pointer
|
||||
SignallingCircuitGroup*& which = net ? m_cicNet : m_cicCpe;
|
||||
SignallingCircuitGroup* tmp = which;
|
||||
// Don't attach if it's the same object
|
||||
SignallingCircuitGroup* tmp = net ? m_cicNet : m_cicCpe;
|
||||
if (tmp == circuits)
|
||||
return;
|
||||
return 0;
|
||||
terminateMonitor(0,circuits ? "circuit group attach" : "circuit group detach");
|
||||
if (tmp && circuits)
|
||||
if (tmp && circuits) {
|
||||
Debug(this,DebugNote,
|
||||
"Attached circuit group (%p) '%s' while we already have one (%p) '%s'",
|
||||
circuits,circuits->debugName(),tmp,tmp->debugName());
|
||||
else if (circuits && !tmp)
|
||||
DDebug(this,DebugAll,"Circuit group (%p) '%s' attached",circuits,circuits->debugName());
|
||||
else if (tmp && !circuits)
|
||||
DDebug(this,DebugAll,"Circuit group (%p) '%s' detached",tmp,tmp->debugName());
|
||||
if (net)
|
||||
m_cicNet = circuits;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else if (circuits)
|
||||
Debug(this,DebugAll,"Circuit group (%p) '%s' attached",circuits,circuits->debugName());
|
||||
else
|
||||
m_cicCpe = circuits;
|
||||
}
|
||||
|
||||
// Get a pointer to this call controller
|
||||
void* ISDNQ931Monitor::getObject(const String& name) const
|
||||
{
|
||||
if (name == "ISDNQ931Monitor")
|
||||
return (void*)this;
|
||||
return SignallingComponent::getObject(name);
|
||||
Debug(this,DebugAll,"Circuit group (%p) '%s' detached",tmp,tmp->debugName());
|
||||
#endif
|
||||
which = circuits;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// Method called periodically to check timeouts
|
||||
|
|
|
@ -115,9 +115,66 @@ int SS7Route::transmitMSU(const SS7Router* router, const SS7MSU& msu,
|
|||
* SS7Router
|
||||
*/
|
||||
SS7Router::SS7Router(const NamedList& params)
|
||||
: Mutex(true), m_changes(0)
|
||||
: SignallingComponent(params.safe("SS7Router"),¶ms),
|
||||
Mutex(true,"SS7Router"), m_changes(0)
|
||||
{
|
||||
setName("ss7router");
|
||||
#ifdef DEBUG
|
||||
if (debugAt(DebugAll)) {
|
||||
String tmp;
|
||||
params.dump(tmp,"\r\n ",'\'',true);
|
||||
Debug(this,DebugAll,"SS7Router::SS7Router(%p) [%p]%s",
|
||||
¶ms,this,tmp.c_str());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SS7Router::initialize(const NamedList* config)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
String tmp;
|
||||
if (config && debugAt(DebugAll))
|
||||
config->dump(tmp,"\r\n ",'\'',true);
|
||||
Debug(this,DebugInfo,"SS7Router::initialize(%p) [%p]%s",config,this,tmp.c_str());
|
||||
#endif
|
||||
if (config) {
|
||||
debugLevel(config->getIntValue("debuglevel_router",
|
||||
config->getIntValue("debuglevel",-1)));
|
||||
const String* param = config->getParam("management");
|
||||
const char* name = "ss7snm";
|
||||
if (param)
|
||||
name = param->c_str();
|
||||
else
|
||||
param = config;
|
||||
if (param->toBoolean(true)) {
|
||||
NamedPointer* ptr = YOBJECT(NamedPointer,param);
|
||||
NamedList* mConfig = ptr ? YOBJECT(NamedList,ptr->userData()) : 0;
|
||||
NamedList params(name);
|
||||
params.addParam("basename",name);
|
||||
if (mConfig)
|
||||
params.copyParams(*mConfig);
|
||||
else
|
||||
mConfig = ¶ms;
|
||||
attach(YSIGCREATE(SS7Management,¶ms));
|
||||
}
|
||||
param = config->getParam("maintenance");
|
||||
name = "ss7mtn";
|
||||
if (param)
|
||||
name = param->c_str();
|
||||
else
|
||||
param = config;
|
||||
if (param->toBoolean(true)) {
|
||||
NamedPointer* ptr = YOBJECT(NamedPointer,param);
|
||||
NamedList* mConfig = ptr ? YOBJECT(NamedList,ptr->userData()) : 0;
|
||||
NamedList params(name);
|
||||
params.addParam("basename",name);
|
||||
if (mConfig)
|
||||
params.copyParams(*mConfig);
|
||||
else
|
||||
mConfig = ¶ms;
|
||||
attach(YSIGCREATE(SS7Maintenance,¶ms));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SS7Router::operational(int sls) const
|
||||
|
@ -224,14 +281,6 @@ void SS7Router::detach(SS7Layer4* service)
|
|||
}
|
||||
}
|
||||
|
||||
void* SS7Router::getObject(const String& name) const
|
||||
{
|
||||
if (name == "SS7Router")
|
||||
return (void*)this;
|
||||
void* p = SS7L3User::getObject(name);
|
||||
return p ? p : SS7Layer3::getObject(name);
|
||||
}
|
||||
|
||||
int SS7Router::transmitMSU(const SS7MSU& msu, const SS7Label& label, int sls)
|
||||
{
|
||||
XDebug(this,DebugStub,"Possibly incomplete SS7Router::transmitMSU(%p,%p,%d)",
|
||||
|
|
|
@ -48,12 +48,12 @@ TokenDict SignallingCircuit::s_lockNames[] = {
|
|||
*/
|
||||
SignallingCallControl::SignallingCallControl(const NamedList& params,
|
||||
const char* msgPrefix)
|
||||
: Mutex(true),
|
||||
m_verifyEvent(false),
|
||||
m_verifyTimer(0),
|
||||
m_circuits(0),
|
||||
m_strategy(SignallingCircuitGroup::Increment),
|
||||
m_exiting(false)
|
||||
: Mutex(true,"SignallingCallControl"),
|
||||
m_verifyEvent(false),
|
||||
m_verifyTimer(0),
|
||||
m_circuits(0),
|
||||
m_strategy(SignallingCircuitGroup::Increment),
|
||||
m_exiting(false)
|
||||
{
|
||||
// Strategy
|
||||
const char* strategy = params.getValue("strategy","increment");
|
||||
|
@ -86,29 +86,31 @@ SignallingCallControl::~SignallingCallControl()
|
|||
}
|
||||
|
||||
// Attach a signalling circuit group. Set its strategy
|
||||
void SignallingCallControl::attach(SignallingCircuitGroup* circuits)
|
||||
SignallingCircuitGroup* SignallingCallControl::attach(SignallingCircuitGroup* circuits)
|
||||
{
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
// Don't attach if it's the same object
|
||||
if (m_circuits == circuits)
|
||||
return;
|
||||
return 0;
|
||||
cleanup(circuits ? "circuit group attach" : "circuit group detach");
|
||||
if (m_circuits && circuits)
|
||||
Debug(DebugNote,
|
||||
"SignallingCallControl. Replaced circuit group (%p) with (%p) [%p]",
|
||||
"SignallingCallControl. Replacing circuit group (%p) with (%p) [%p]",
|
||||
m_circuits,circuits,this);
|
||||
SignallingCircuitGroup* tmp = m_circuits;
|
||||
m_circuits = circuits;
|
||||
if (m_circuits) {
|
||||
Lock lock(m_circuits);
|
||||
m_circuits->setStrategy(m_strategy);
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// Reserve a circuit from a given list in attached group
|
||||
bool SignallingCallControl::reserveCircuit(SignallingCircuit*& cic, const char* range,
|
||||
int checkLock, const String* list, bool mandatory, bool reverseRestrict)
|
||||
{
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
releaseCircuit(cic);
|
||||
if (!m_circuits)
|
||||
return false;
|
||||
|
@ -143,7 +145,7 @@ bool SignallingCallControl::releaseCircuit(SignallingCircuit*& cic, bool sync)
|
|||
|
||||
bool SignallingCallControl::releaseCircuit(unsigned int code, bool sync)
|
||||
{
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
SignallingCircuit* cic = m_circuits ? m_circuits->find(code) : 0;
|
||||
if (!cic)
|
||||
return false;
|
||||
|
@ -232,29 +234,29 @@ void SignallingCallControl::removeCall(SignallingCall* call, bool del)
|
|||
* SignallingCall
|
||||
*/
|
||||
SignallingCall::SignallingCall(SignallingCallControl* controller, bool outgoing, bool signalOnly)
|
||||
: m_callMutex(true),
|
||||
: Mutex(true,"SignallingCall"),
|
||||
m_lastEvent(0),
|
||||
m_controller(controller),
|
||||
m_outgoing(outgoing),
|
||||
m_signalOnly(signalOnly),
|
||||
m_inMsgMutex(true),
|
||||
m_inMsgMutex(true,"SignallingCall::inMsg"),
|
||||
m_private(0)
|
||||
{
|
||||
}
|
||||
|
||||
SignallingCall::~SignallingCall()
|
||||
{
|
||||
m_callMutex.lock();
|
||||
lock();
|
||||
m_inMsg.clear();
|
||||
if (m_controller)
|
||||
m_controller->removeCall(this,false);
|
||||
m_callMutex.unlock();
|
||||
unlock();
|
||||
}
|
||||
|
||||
// Event termination notification
|
||||
void SignallingCall::eventTerminated(SignallingEvent* event)
|
||||
{
|
||||
Lock lock(m_callMutex);
|
||||
Lock mylock(this);
|
||||
if (!m_lastEvent || !event || m_lastEvent != event)
|
||||
return;
|
||||
XDebug(DebugAll,"SignallingCall. Event (%p,'%s') terminated [%p]",event,event->name(),this);
|
||||
|
@ -401,28 +403,22 @@ static TokenDict s_cicStatusDict[] = {
|
|||
|
||||
SignallingCircuit::SignallingCircuit(Type type, unsigned int code,
|
||||
SignallingCircuitGroup* group, SignallingCircuitSpan* span)
|
||||
: m_mutex(true),
|
||||
m_group(group),
|
||||
m_span(span),
|
||||
m_code(code),
|
||||
m_type(type),
|
||||
m_status(Disabled),
|
||||
m_lock(0),
|
||||
m_lastEvent(0)
|
||||
: m_mutex(true,"SignallingCircuit::operations"),
|
||||
m_group(group), m_span(span),
|
||||
m_code(code), m_type(type),
|
||||
m_status(Disabled),
|
||||
m_lock(0), m_lastEvent(0)
|
||||
{
|
||||
XDebug(m_group,DebugAll,"SignallingCircuit::SignallingCircuit [%p]",this);
|
||||
}
|
||||
|
||||
SignallingCircuit::SignallingCircuit(Type type, unsigned int code, Status status,
|
||||
SignallingCircuitGroup* group, SignallingCircuitSpan* span)
|
||||
: m_mutex(true),
|
||||
m_group(group),
|
||||
m_span(span),
|
||||
m_code(code),
|
||||
m_type(type),
|
||||
m_status(status),
|
||||
m_lock(0),
|
||||
m_lastEvent(0)
|
||||
: m_mutex(true,"SignallingCircuit::operations"),
|
||||
m_group(group), m_span(span),
|
||||
m_code(code), m_type(type),
|
||||
m_status(status),
|
||||
m_lock(0), m_lastEvent(0)
|
||||
{
|
||||
XDebug(m_group,DebugAll,"SignallingCircuit::SignallingCircuit [%p]",this);
|
||||
}
|
||||
|
@ -530,13 +526,12 @@ const char* SignallingCircuit::lookupStatus(int status)
|
|||
/**
|
||||
* SignallingCircuitRange
|
||||
*/
|
||||
SignallingCircuitRange::SignallingCircuitRange(const String& rangeStr, const char* name,
|
||||
int strategy)
|
||||
SignallingCircuitRange::SignallingCircuitRange(const String& rangeStr,
|
||||
const char* name, int strategy)
|
||||
: String(name),
|
||||
m_count(0),
|
||||
m_last(0),
|
||||
m_strategy(strategy),
|
||||
m_used(0)
|
||||
m_count(0), m_last(0),
|
||||
m_strategy(strategy),
|
||||
m_used(0)
|
||||
{
|
||||
add(rangeStr);
|
||||
}
|
||||
|
@ -607,13 +602,11 @@ TokenDict SignallingCircuitGroup::s_strategy[] = {
|
|||
{0,0}
|
||||
};
|
||||
|
||||
YCLASSIMP(SignallingCircuitGroup,SignallingComponent)
|
||||
|
||||
SignallingCircuitGroup::SignallingCircuitGroup(unsigned int base, int strategy, const char* name)
|
||||
: SignallingComponent(name),
|
||||
Mutex(true),
|
||||
m_range(String::empty(),name,strategy),
|
||||
m_base(base)
|
||||
Mutex(true,"SignallingCircuitGroup"),
|
||||
m_range(String::empty(),name,strategy),
|
||||
m_base(base)
|
||||
{
|
||||
setName(name);
|
||||
XDebug(this,DebugAll,"SignallingCircuitGroup::SignallingCircuitGroup() [%p]",this);
|
||||
|
@ -635,7 +628,7 @@ SignallingCircuit* SignallingCircuitGroup::find(unsigned int cic, bool local)
|
|||
return 0;
|
||||
cic -= m_base;
|
||||
}
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
if (cic >= m_range.m_last)
|
||||
return 0;
|
||||
ObjList* l = m_circuits.skipNull();
|
||||
|
@ -650,7 +643,7 @@ SignallingCircuit* SignallingCircuitGroup::find(unsigned int cic, bool local)
|
|||
// Find a range of circuits owned by this group
|
||||
SignallingCircuitRange* SignallingCircuitGroup::findRange(const char* name)
|
||||
{
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
ObjList* obj = m_ranges.find(name);
|
||||
return obj ? static_cast<SignallingCircuitRange*>(obj->get()) : 0;
|
||||
}
|
||||
|
@ -658,7 +651,7 @@ SignallingCircuitRange* SignallingCircuitGroup::findRange(const char* name)
|
|||
void SignallingCircuitGroup::getCicList(String& dest)
|
||||
{
|
||||
dest = "";
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
for (ObjList* l = m_circuits.skipNull(); l; l = l->skipNext()) {
|
||||
SignallingCircuit* c = static_cast<SignallingCircuit*>(l->get());
|
||||
dest.append(String(c->code()),",");
|
||||
|
@ -670,7 +663,7 @@ bool SignallingCircuitGroup::insert(SignallingCircuit* circuit)
|
|||
{
|
||||
if (!circuit)
|
||||
return false;
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
if (m_circuits.find(circuit) || find(circuit->code(),true))
|
||||
return false;
|
||||
circuit->m_group = this;
|
||||
|
@ -684,7 +677,7 @@ void SignallingCircuitGroup::remove(SignallingCircuit* circuit)
|
|||
{
|
||||
if (!circuit)
|
||||
return;
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
if (!m_circuits.remove(circuit,false))
|
||||
return;
|
||||
circuit->m_group = 0;
|
||||
|
@ -697,12 +690,34 @@ bool SignallingCircuitGroup::insertSpan(SignallingCircuitSpan* span)
|
|||
{
|
||||
if (!span)
|
||||
return false;
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
if (!m_spans.find(span))
|
||||
m_spans.append(span);
|
||||
return true;
|
||||
}
|
||||
|
||||
SignallingCircuitSpan* SignallingCircuitGroup::buildSpan(const String& name, unsigned int start)
|
||||
{
|
||||
// Local class used to pass the circuit group pointer to the span
|
||||
class VoiceParams : public NamedList
|
||||
{
|
||||
public:
|
||||
inline VoiceParams(const char* name, SignallingCircuitGroup* group)
|
||||
: NamedList(name), m_group(group)
|
||||
{ }
|
||||
virtual void* getObject(const String& name) const
|
||||
{ return (name == "SignallingCircuitGroup") ? m_group : NamedList::getObject(name); }
|
||||
SignallingCircuitGroup* m_group;
|
||||
};
|
||||
|
||||
VoiceParams params(debugName(),this);
|
||||
params << "/" << name;
|
||||
params.addParam("voice",name);
|
||||
if (start)
|
||||
params.addParam("start",String(start));
|
||||
return YSIGCREATE(SignallingCircuitSpan,¶ms);
|
||||
}
|
||||
|
||||
// Build and insert a range from circuits belonging to a given span
|
||||
void SignallingCircuitGroup::insertRange(SignallingCircuitSpan* span, const char* name,
|
||||
int strategy)
|
||||
|
@ -711,14 +726,14 @@ void SignallingCircuitGroup::insertRange(SignallingCircuitSpan* span, const char
|
|||
return;
|
||||
if (!name)
|
||||
name = span->id();
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
String tmp;
|
||||
for (ObjList* o = m_circuits.skipNull(); o; o = o->skipNext()) {
|
||||
SignallingCircuit* c = static_cast<SignallingCircuit*>(o->get());
|
||||
if (span == c->span())
|
||||
tmp.append(String(c->code()),",");
|
||||
}
|
||||
lock.drop();
|
||||
mylock.drop();
|
||||
insertRange(tmp,name,strategy);
|
||||
}
|
||||
|
||||
|
@ -726,7 +741,7 @@ void SignallingCircuitGroup::insertRange(SignallingCircuitSpan* span, const char
|
|||
void SignallingCircuitGroup::insertRange(const String& range, const char* name,
|
||||
int strategy)
|
||||
{
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
if (findRange(name))
|
||||
return;
|
||||
if (strategy < 0)
|
||||
|
@ -740,7 +755,7 @@ void SignallingCircuitGroup::removeSpan(SignallingCircuitSpan* span, bool delCic
|
|||
{
|
||||
if (!span)
|
||||
return;
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
if (delCics)
|
||||
removeSpanCircuits(span);
|
||||
m_spans.remove(span,delSpan);
|
||||
|
@ -751,7 +766,7 @@ void SignallingCircuitGroup::removeSpanCircuits(SignallingCircuitSpan* span)
|
|||
{
|
||||
if (!span)
|
||||
return;
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
ListIterator iter(m_circuits);
|
||||
for (GenObject* obj = 0; (obj = iter.get());) {
|
||||
SignallingCircuit* c = static_cast<SignallingCircuit*>(obj);
|
||||
|
@ -765,7 +780,7 @@ void SignallingCircuitGroup::removeSpanCircuits(SignallingCircuitSpan* span)
|
|||
// Get the status of a circuit given by its code
|
||||
SignallingCircuit::Status SignallingCircuitGroup::status(unsigned int cic)
|
||||
{
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
SignallingCircuit* circuit = find(cic);
|
||||
return circuit ? circuit->status() : SignallingCircuit::Missing;
|
||||
}
|
||||
|
@ -774,7 +789,7 @@ SignallingCircuit::Status SignallingCircuitGroup::status(unsigned int cic)
|
|||
bool SignallingCircuitGroup::status(unsigned int cic, SignallingCircuit::Status newStat,
|
||||
bool sync)
|
||||
{
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
SignallingCircuit* circuit = find(cic);
|
||||
return circuit && circuit->status(newStat,sync);
|
||||
}
|
||||
|
@ -820,7 +835,7 @@ unsigned int SignallingCircuitGroup::advance(unsigned int n, int strategy,
|
|||
SignallingCircuit* SignallingCircuitGroup::reserve(int checkLock, int strategy,
|
||||
SignallingCircuitRange* range)
|
||||
{
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
if (!range)
|
||||
range = &m_range;
|
||||
if (range->m_last < 1)
|
||||
|
@ -875,7 +890,7 @@ SignallingCircuit* SignallingCircuitGroup::reserve(int checkLock, int strategy,
|
|||
if (n == start)
|
||||
break;
|
||||
}
|
||||
lock.drop();
|
||||
mylock.drop();
|
||||
if (strategy & Fallback) {
|
||||
if (strategy & OnlyEven) {
|
||||
Debug(this,DebugNote,"No even circuits available, falling back to odd [%p]",this);
|
||||
|
@ -894,7 +909,7 @@ SignallingCircuit* SignallingCircuitGroup::reserve(int checkLock, int strategy,
|
|||
SignallingCircuit* SignallingCircuitGroup::reserve(const String& list, bool mandatory,
|
||||
int checkLock, int strategy, SignallingCircuitRange* range)
|
||||
{
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
if (!range)
|
||||
range = &m_range;
|
||||
// Check if any of the given circuits are free
|
||||
|
@ -932,7 +947,7 @@ SignallingCircuit* SignallingCircuitGroup::reserve(const String& list, bool mand
|
|||
// Clear data
|
||||
void SignallingCircuitGroup::clearAll()
|
||||
{
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
// Remove spans and their circuits
|
||||
ListIterator iter(m_spans);
|
||||
for (GenObject* obj = 0; (obj = iter.get());)
|
||||
|
@ -953,8 +968,8 @@ void SignallingCircuitGroup::clearAll()
|
|||
* SignallingCircuitSpan
|
||||
*/
|
||||
SignallingCircuitSpan::SignallingCircuitSpan(const char* id, SignallingCircuitGroup* group)
|
||||
: m_group(group),
|
||||
m_id(id)
|
||||
: SignallingComponent(id),
|
||||
m_group(group), m_increment(0), m_id(id)
|
||||
{
|
||||
if (m_group)
|
||||
m_group->insertSpan(this);
|
||||
|
@ -1018,7 +1033,7 @@ inline u_int64_t getValidInt(const NamedList& params, const char* param, int def
|
|||
|
||||
// Reserve the line's circuit
|
||||
AnalogLine::AnalogLine(AnalogLineGroup* grp, unsigned int cic, const NamedList& params)
|
||||
: Mutex(true),
|
||||
: Mutex(true,"AnalogLine"),
|
||||
m_type(Unknown),
|
||||
m_state(Idle),
|
||||
m_inband(false),
|
||||
|
@ -1095,7 +1110,7 @@ AnalogLine::~AnalogLine()
|
|||
// Remove old peer's peer. Set this line's peer
|
||||
void AnalogLine::setPeer(AnalogLine* line, bool sync)
|
||||
{
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
if (line == this) {
|
||||
Debug(m_group,DebugNote,"%s: Attempt to set peer to itself [%p]",
|
||||
address(),this);
|
||||
|
@ -1140,7 +1155,7 @@ void AnalogLine::resetEcho(bool train)
|
|||
// Connect the line's circuit. Reset line echo canceller
|
||||
bool AnalogLine::connect(bool sync)
|
||||
{
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
bool ok = m_circuit && m_circuit->connect();
|
||||
resetEcho(true);
|
||||
if (sync && ok && m_peer)
|
||||
|
@ -1151,7 +1166,7 @@ bool AnalogLine::connect(bool sync)
|
|||
// Disconnect the line's circuit. Reset line echo canceller
|
||||
bool AnalogLine::disconnect(bool sync)
|
||||
{
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
bool ok = m_circuit && m_circuit->disconnect();
|
||||
resetEcho(false);
|
||||
if (sync && ok && m_peer)
|
||||
|
@ -1162,7 +1177,7 @@ bool AnalogLine::disconnect(bool sync)
|
|||
// Send an event through this line
|
||||
bool AnalogLine::sendEvent(SignallingCircuitEvent::Type type, NamedList* params)
|
||||
{
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
if (state() == OutOfService)
|
||||
return false;
|
||||
if (m_inband &&
|
||||
|
@ -1174,7 +1189,7 @@ bool AnalogLine::sendEvent(SignallingCircuitEvent::Type type, NamedList* params)
|
|||
// Get events from the line's circuit if not out of service
|
||||
AnalogLineEvent* AnalogLine::getEvent(const Time& when)
|
||||
{
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
if (state() == OutOfService) {
|
||||
checkTimeouts(when);
|
||||
return 0;
|
||||
|
@ -1201,7 +1216,7 @@ AnalogLineEvent* AnalogLine::getEvent(const Time& when)
|
|||
// Alternate get events from this line or peer
|
||||
AnalogLineEvent* AnalogLine::getMonitorEvent(const Time& when)
|
||||
{
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
m_getPeerEvent = !m_getPeerEvent;
|
||||
AnalogLineEvent* event = 0;
|
||||
if (m_getPeerEvent) {
|
||||
|
@ -1221,7 +1236,7 @@ AnalogLineEvent* AnalogLine::getMonitorEvent(const Time& when)
|
|||
// Change the line state if neither current or new state are OutOfService
|
||||
bool AnalogLine::changeState(State newState, bool sync)
|
||||
{
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
bool ok = false;
|
||||
while (true) {
|
||||
if (m_state == newState || m_state == OutOfService || newState == OutOfService)
|
||||
|
@ -1244,7 +1259,7 @@ bool AnalogLine::changeState(State newState, bool sync)
|
|||
// entering/exiting the OutOfService state
|
||||
bool AnalogLine::enable(bool ok, bool sync, bool connectNow)
|
||||
{
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
while (true) {
|
||||
if (ok) {
|
||||
if (m_state != OutOfService)
|
||||
|
@ -1293,8 +1308,6 @@ void AnalogLine::destroyed()
|
|||
* AnalogLineGroup
|
||||
*/
|
||||
|
||||
YCLASSIMP(AnalogLineGroup,SignallingCircuitGroup)
|
||||
|
||||
// Construct an analog line group owning single lines
|
||||
AnalogLineGroup::AnalogLineGroup(AnalogLine::Type type, const char* name, bool slave)
|
||||
: SignallingCircuitGroup(0,SignallingCircuitGroup::Increment,name),
|
||||
|
@ -1338,7 +1351,7 @@ bool AnalogLineGroup::appendLine(AnalogLine* line, bool destructOnFail)
|
|||
TelEngine::destruct(line);
|
||||
return false;
|
||||
}
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
m_lines.append(line);
|
||||
DDebug(this,DebugAll,"Added line (%p) %s [%p]",line,line->address(),this);
|
||||
return true;
|
||||
|
@ -1347,7 +1360,7 @@ bool AnalogLineGroup::appendLine(AnalogLine* line, bool destructOnFail)
|
|||
// Remove a line from the list and destruct it
|
||||
void AnalogLineGroup::removeLine(unsigned int cic)
|
||||
{
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
AnalogLine* line = findLine(cic);
|
||||
if (!line)
|
||||
return;
|
||||
|
@ -1360,7 +1373,7 @@ void AnalogLineGroup::removeLine(AnalogLine* line)
|
|||
{
|
||||
if (!line)
|
||||
return;
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
if (m_lines.remove(line,false))
|
||||
DDebug(this,DebugAll,"Removed line %p %s [%p]",line,line->address(),this);
|
||||
}
|
||||
|
@ -1368,7 +1381,7 @@ void AnalogLineGroup::removeLine(AnalogLine* line)
|
|||
// Find a line by its circuit
|
||||
AnalogLine* AnalogLineGroup::findLine(unsigned int cic)
|
||||
{
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
for (ObjList* o = m_lines.skipNull(); o; o = o->skipNext()) {
|
||||
AnalogLine* line = static_cast<AnalogLine*>(o->get());
|
||||
if (line->circuit() && line->circuit()->code() == cic)
|
||||
|
@ -1380,7 +1393,7 @@ AnalogLine* AnalogLineGroup::findLine(unsigned int cic)
|
|||
// Find a line by its address
|
||||
AnalogLine* AnalogLineGroup::findLine(const String& address)
|
||||
{
|
||||
Lock lock(this);
|
||||
Lock mylock(this);
|
||||
ObjList* tmp = m_lines.find(address);
|
||||
return tmp ? static_cast<AnalogLine*>(tmp->get()) : 0;
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ const TokenDict* SIGTRAN::classNames()
|
|||
}
|
||||
|
||||
SIGTRAN::SIGTRAN()
|
||||
: m_trans(0)
|
||||
: m_trans(0), m_transMutex(false,"SIGTRAN::transport")
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* tcap.cpp
|
||||
* tup.cpp
|
||||
* This file is part of the YATE Project http://YATE.null.ro
|
||||
*
|
||||
* Yet Another Signalling Stack - implements the support for SS7, ISDN and PSTN
|
||||
|
@ -28,7 +28,8 @@
|
|||
using namespace TelEngine;
|
||||
|
||||
SS7TUP::SS7TUP(const NamedList& params)
|
||||
: SignallingCallControl(params,"tup.")
|
||||
: SignallingComponent("SS7TUP",¶ms),
|
||||
SignallingCallControl(params,"tup.")
|
||||
{
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -31,9 +31,6 @@ namespace { // anonymous
|
|||
class ModuleLine; // Module's interface to an analog line or recorder
|
||||
// Manages the call setup detector and sends call setup info
|
||||
class ModuleGroup; // Module's interface to a group of lines
|
||||
class AnalogParams; // Named list containing creator data (pointers)
|
||||
// Used to pass parameters to objects that need to obtain some
|
||||
// pointers from the creator
|
||||
class AnalogChannel; // Channel associated with an analog line
|
||||
class AnalogCallRec; // Recorder call endpoint associated with an analog line monitor
|
||||
class AnalogDriver; // Analog driver
|
||||
|
@ -186,23 +183,6 @@ private:
|
|||
ObjList m_endpoints; // Record data endpoints
|
||||
};
|
||||
|
||||
// Named list containing creator data (pointers)
|
||||
// Used to pass parameters to objects that need to obtain some pointers
|
||||
class AnalogParams : public NamedList
|
||||
{
|
||||
public:
|
||||
inline AnalogParams(const char* name, SignallingCircuitGroup* group)
|
||||
: NamedList(name), m_cicGroup(group)
|
||||
{}
|
||||
virtual void* getObject(const String& name) const {
|
||||
if (name == "SignallingCircuitGroup")
|
||||
return m_cicGroup;
|
||||
return NamedList::getObject(name);
|
||||
}
|
||||
private:
|
||||
SignallingCircuitGroup* m_cicGroup;
|
||||
};
|
||||
|
||||
// Channel associated with an analog line
|
||||
class AnalogChannel : public Channel
|
||||
{
|
||||
|
@ -991,7 +971,7 @@ bool ModuleGroup::initialize(const NamedList& params, const NamedList& defaults,
|
|||
if (!m_init)
|
||||
debugChain(&plugin);
|
||||
|
||||
int level = params.getIntValue("debuglevel",m_init ? debugLevel() : plugin.debugLevel());
|
||||
int level = params.getIntValue("debuglevel",m_init ? DebugEnabler::debugLevel() : plugin.debugLevel());
|
||||
if (level >= 0) {
|
||||
debugEnabled(0 != level);
|
||||
debugLevel(level);
|
||||
|
@ -1306,26 +1286,17 @@ void ModuleGroup::buildGroup(ModuleGroup* group, ObjList& spanList, String& erro
|
|||
{
|
||||
if (!group)
|
||||
return;
|
||||
int start = 0;
|
||||
unsigned int start = 0;
|
||||
for (ObjList* o = spanList.skipNull(); o; o = o->skipNext()) {
|
||||
String* s = static_cast<String*>(o->get());
|
||||
if (!s)
|
||||
if (s->null())
|
||||
continue;
|
||||
AnalogParams spanParams("voice",group);
|
||||
String tmp;
|
||||
tmp << group->debugName() << "/" << *s;
|
||||
spanParams.addParam("debugname",tmp);
|
||||
spanParams.addParam("voice",*s);
|
||||
if (start)
|
||||
spanParams.addParam("start",String(start));
|
||||
SignallingCircuitSpan* span = static_cast<SignallingCircuitSpan*>(
|
||||
SignallingFactory::build(spanParams,&spanParams));
|
||||
SignallingCircuitSpan* span = buildSpan(*s,start);
|
||||
if (!span) {
|
||||
error << "Failed to build span '" << *s << "'";
|
||||
break;
|
||||
}
|
||||
int chans = spanParams.getIntValue("chans");
|
||||
start += chans;
|
||||
start += span->increment();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -228,7 +228,7 @@ public:
|
|||
// Handle the data received from Rudp
|
||||
void handleData(DataBlock& data);
|
||||
// Send start stop messages
|
||||
void initSesion();
|
||||
void initSession();
|
||||
bool sendData(DataBlock& data, bool connectR = false);
|
||||
// Find a specific user
|
||||
bool insert(SessionUser* user);
|
||||
|
@ -275,6 +275,7 @@ protected:
|
|||
|
||||
class SLT : public SS7Layer2, public SessionUser
|
||||
{
|
||||
YCLASS(SLT,SS7Layer2)
|
||||
public:
|
||||
enum Messages {
|
||||
Connect_R = 0x06, // Connect Request message
|
||||
|
@ -417,7 +418,7 @@ public:
|
|||
{return lookup((int)state, s_linkCongestion);}
|
||||
static inline const char* sprotocolError(protocolError state)
|
||||
{return lookup((int)state, s_protocolError);}
|
||||
static void* create(const String& type,const NamedList& params);
|
||||
static SignallingComponent* create(const String& type,const NamedList& params);
|
||||
protected:
|
||||
unsigned int m_status; // Layer status
|
||||
unsigned int m_lStatus; // Local layer status
|
||||
|
@ -559,10 +560,10 @@ bool RudpSocket::initialize(const NamedList& params)
|
|||
m_sequence = 0;
|
||||
}
|
||||
m_cumAckTimer.interval(params,"rudp_cumulative",100,300,false);
|
||||
m_nullTimer.interval(params,"rudp_nulltimer",1900,2000,false);
|
||||
m_retransTimer.interval(params,"rudp_retransmissiontimer",400,600,false);
|
||||
m_nullTimer.interval(params,"rudp_nulltimer",1500,2000,false);
|
||||
m_retransTimer.interval(params,"rudp_retransmission",400,600,false);
|
||||
m_synTimer.interval(params,"rudp_syntimer",900,1000,false);
|
||||
m_retransCounter = params.getIntValue("rudp_maxretransmission",2);
|
||||
m_retransCounter = params.getIntValue("rudp_maxretrans",2);
|
||||
m_maxCumAck = params.getIntValue("rudp_maxcumulative",3);
|
||||
m_haveChecksum = params.getBoolValue("rudp_checksum",false);
|
||||
m_sendSyn = params.getBoolValue("rudp_sendsyn",false);
|
||||
|
@ -581,7 +582,7 @@ bool RudpSocket::initSocket(const NamedList& params)
|
|||
{
|
||||
m_socket = new Socket(AF_INET,SOCK_DGRAM);
|
||||
String rhost = params.getValue("remote_host");
|
||||
unsigned int rport = params.getIntValue("remote_port");
|
||||
unsigned int rport = params.getIntValue("remote_port",8060);
|
||||
if (!rhost || !rport) {
|
||||
Debug(m_sm,DebugStub, "Unable to initialize socket, remote%s%s%s is missing",
|
||||
rhost ? "" : " host",
|
||||
|
@ -1192,7 +1193,7 @@ void SessionManager::notify(bool down)
|
|||
informUser(false);
|
||||
} else {
|
||||
changeState(Operational);
|
||||
initSesion();
|
||||
initSession();
|
||||
informUser(true);
|
||||
}
|
||||
}
|
||||
|
@ -1215,7 +1216,7 @@ void SessionManager::handleData(DataBlock& data)
|
|||
}
|
||||
|
||||
// Session Initialization send standby and active messages
|
||||
void SessionManager::initSesion()
|
||||
void SessionManager::initSession()
|
||||
{
|
||||
if (!m_socket)
|
||||
return;
|
||||
|
@ -1264,8 +1265,10 @@ bool SessionManager::sendData(DataBlock& data, bool connectR)
|
|||
if (!m_socket || m_state != Operational)
|
||||
return false;
|
||||
// Send Standby and Active messages if we have an connect request message and all users are down
|
||||
if (connectR && m_upUsers == 0)
|
||||
initSesion();
|
||||
if (connectR && m_upUsers == 0) {
|
||||
initSession();
|
||||
DDebug(this,DebugAll,"Sending init delayed PDU data: %u bytes",data.length());
|
||||
}
|
||||
m_socket->sendMSG(data);
|
||||
return true;
|
||||
}
|
||||
|
@ -1318,7 +1321,7 @@ void SessionManager::changeState(State newState)
|
|||
m_state = newState;
|
||||
}
|
||||
|
||||
// As far as we know these messages should be send by us
|
||||
// As far as we know these messages should be sent by us
|
||||
void SessionManager::handleSmMessage(u_int32_t smMessageType)
|
||||
{
|
||||
switch (smMessageType) {
|
||||
|
@ -1463,7 +1466,7 @@ const TokenDict SLT::s_protocolError[] = {
|
|||
};
|
||||
|
||||
SLT::SLT(const String& name, const NamedList& param)
|
||||
: SessionUser(1),
|
||||
: SignallingComponent(param.safe("CiscoSLT")), SessionUser(1),
|
||||
m_status(Unconfigured), m_lStatus(NormalAlignment), m_rStatus(OutOfAlignment),
|
||||
m_reqStatus(NormalAlignment), m_messageId(1), m_channelId(0), m_bearerId(0),
|
||||
m_confReqTimer(0), m_printMsg(false)
|
||||
|
@ -1476,7 +1479,7 @@ SLT::SLT(const String& name, const NamedList& param)
|
|||
m_session->insert(this);
|
||||
m_session->deref();
|
||||
}
|
||||
m_confReqTimer.interval(param,"configuration",59,60,true);
|
||||
m_confReqTimer.interval(param,"configuration",250,5000,true);
|
||||
m_printMsg = param.getBoolValue("printslt",false);
|
||||
}
|
||||
|
||||
|
@ -1909,24 +1912,23 @@ bool SLT::operational() const
|
|||
return aligned();
|
||||
}
|
||||
|
||||
void* SLT::create(const String& type, const NamedList& name)
|
||||
SignallingComponent* SLT::create(const String& type, const NamedList& name)
|
||||
{
|
||||
if (type != "SS7l2")
|
||||
if (type != "SS7Layer2")
|
||||
return 0;
|
||||
Configuration cfg(Engine::configFile("ciscosm"));
|
||||
const char* sectName = name.getValue("name");
|
||||
const char* sectName = name.getValue("link",name);
|
||||
NamedList* layer = cfg.getSection(sectName);
|
||||
if (!layer)
|
||||
return 0;
|
||||
String confSec = layer->getValue("session","default");
|
||||
NamedList* section = cfg.getSection(confSec);
|
||||
if (!section) {
|
||||
Debug(DebugWarn,"Section '%s' does not exist in configuration",confSec.c_str());
|
||||
Debug(DebugWarn,"Session '%s' does not exist in configuration",confSec.c_str());
|
||||
return 0;
|
||||
}
|
||||
layer->copyParams(*section);
|
||||
SLT* slt = new SLT(name,*layer);
|
||||
return slt;
|
||||
return new SLT(name,*layer);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -110,7 +110,7 @@ public:
|
|||
inline bool fxs() const
|
||||
{ return m_fxs; }
|
||||
bool ownsId(const String& rqId) const;
|
||||
static void* create(const String& type, const NamedList& name);
|
||||
static SignallingComponent* create(const String& type, const NamedList& name);
|
||||
static MGCPSpan* findNotify(const String& id);
|
||||
bool matchEndpoint(const MGCPEndpointId& ep);
|
||||
bool processEvent(MGCPTransaction* tr, MGCPMessage* mm);
|
||||
|
@ -251,7 +251,7 @@ static bool copyRename(NamedList& dest, const char* dname, const NamedList& src,
|
|||
}
|
||||
|
||||
// Increment the number at the end of a name by an offset
|
||||
static bool increment(String& name, unsigned int offs)
|
||||
static bool tailIncrement(String& name, unsigned int offs)
|
||||
{
|
||||
Regexp r("\\([0-9]\\+\\)@");
|
||||
if (name.matches(r)) {
|
||||
|
@ -674,17 +674,21 @@ bool MGCPWrapper::nativeConnect(DataEndpoint* peer)
|
|||
|
||||
|
||||
// Called by the factory to create MGCP spans
|
||||
void* MGCPSpan::create(const String& type, const NamedList& name)
|
||||
SignallingComponent* MGCPSpan::create(const String& type, const NamedList& name)
|
||||
{
|
||||
if (type != "voice")
|
||||
if (type != "SignallingCircuitSpan")
|
||||
return 0;
|
||||
const String* spanName = name.getParam(type);
|
||||
const String* spanName = name.getParam("voice");
|
||||
if (!spanName)
|
||||
spanName = &name;
|
||||
if (null(spanName) || !s_endpoint)
|
||||
return 0;
|
||||
MGCPEpInfo* ep = s_endpoint->findAlias(*spanName);
|
||||
if (!ep)
|
||||
if (!ep) {
|
||||
DDebug(&splugin,DebugAll,"No endpoint info for span '%s'",spanName->c_str());
|
||||
return 0;
|
||||
MGCPSpan* span = new MGCPSpan(name,spanName->c_str(),*ep);
|
||||
}
|
||||
MGCPSpan* span = new MGCPSpan(name,spanName->safe("MGCPSpan"),*ep);
|
||||
if (span->init(name))
|
||||
return span;
|
||||
TelEngine::destruct(span);
|
||||
|
@ -761,6 +765,10 @@ bool MGCPSpan::init(const NamedList& params)
|
|||
{
|
||||
clearCircuits();
|
||||
const String* sect = params.getParam("voice");
|
||||
if (!sect)
|
||||
sect = params.getParam("basename");
|
||||
if (!sect)
|
||||
sect = ¶ms;
|
||||
int cicStart = params.getIntValue("start");
|
||||
if ((cicStart < 0) || !sect)
|
||||
return false;
|
||||
|
@ -776,6 +784,10 @@ bool MGCPSpan::init(const NamedList& params)
|
|||
|
||||
if (!m_count)
|
||||
return false;
|
||||
m_increment = m_count;
|
||||
// assume 31 circuits means E1
|
||||
if (m_increment == 31)
|
||||
m_increment = 32;
|
||||
m_circuits = new MGCPCircuit*[m_count];
|
||||
unsigned int i;
|
||||
for (i = 0; i < m_count; i++)
|
||||
|
@ -783,7 +795,7 @@ bool MGCPSpan::init(const NamedList& params)
|
|||
bool ok = true;
|
||||
for (i = 0; i < m_count; i++) {
|
||||
String name = epId().id();
|
||||
if (!increment(name,i)) {
|
||||
if (!tailIncrement(name,i)) {
|
||||
Debug(m_group,DebugWarn,"MGCPSpan('%s'). Failed to increment name by %u. Rollback [%p]",
|
||||
id().safe(),i,this);
|
||||
clearCircuits();
|
||||
|
@ -801,8 +813,6 @@ bool MGCPSpan::init(const NamedList& params)
|
|||
}
|
||||
circuit->ref();
|
||||
}
|
||||
if (ok)
|
||||
const_cast<NamedList&>(params).setParam("chans",String(m_count));
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
|
|
@ -224,7 +224,7 @@ public:
|
|||
// Process incoming data
|
||||
virtual bool process();
|
||||
// Called by the factory to create TDM interfaces or spans
|
||||
static void* create(const String& type, const NamedList& name);
|
||||
static SignallingComponent* create(const String& type, const NamedList& name);
|
||||
protected:
|
||||
// Check if received any data in the last interval. Notify receiver
|
||||
virtual void timerTick(const Time& when);
|
||||
|
@ -1106,17 +1106,20 @@ bool TdmSpan::init(TdmDevice::Type type,
|
|||
if (!voice)
|
||||
voice = "1-15.17-31";
|
||||
chans = 31;
|
||||
m_increment = 32;
|
||||
break;
|
||||
case TdmDevice::T1:
|
||||
if (!voice)
|
||||
voice = "1-23";
|
||||
chans = 24;
|
||||
m_increment = 24;
|
||||
break;
|
||||
case TdmDevice::NET:
|
||||
case TdmDevice::CPE:
|
||||
if (!voice)
|
||||
voice = "1.2";
|
||||
chans = 3;
|
||||
m_increment = 3;
|
||||
break;
|
||||
case TdmDevice::FXO:
|
||||
case TdmDevice::FXS:
|
||||
|
@ -1142,12 +1145,11 @@ bool TdmSpan::init(TdmDevice::Type type,
|
|||
}
|
||||
|
||||
if (!digital)
|
||||
chans = count;
|
||||
((NamedList*)¶ms)->setParam("chans",String(chans));
|
||||
m_increment = chans = count;
|
||||
unsigned int start = params.getIntValue("start",0);
|
||||
// Create and insert circuits
|
||||
unsigned int added = 0;
|
||||
DDebug(m_group,DebugGoOn,
|
||||
DDebug(m_group,DebugNote,
|
||||
"TdmSpan('%s'). Creating circuits starting with %u [%p]",
|
||||
id().safe(),start,this);
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
|
@ -1166,7 +1168,7 @@ bool TdmSpan::init(TdmDevice::Type type,
|
|||
continue;
|
||||
}
|
||||
TelEngine::destruct(cic);
|
||||
Debug(m_group,DebugGoOn,
|
||||
Debug(m_group,DebugWarn,
|
||||
"TdmSpan('%s'). Duplicate circuit code=%u (channel=%u) [%p]",
|
||||
id().safe(),code,channel,this);
|
||||
}
|
||||
|
@ -1638,25 +1640,31 @@ bool TdmAnalogCircuit::process()
|
|||
}
|
||||
|
||||
// Interface
|
||||
void* TdmInterface::create(const String& type, const NamedList& name)
|
||||
SignallingComponent* TdmInterface::create(const String& type, const NamedList& name)
|
||||
{
|
||||
bool circuit = true;
|
||||
if (type == "sig")
|
||||
if (type == "SignallingInterface")
|
||||
circuit = false;
|
||||
else if (type == "voice")
|
||||
else if (type == "SignallingCircuitSpan")
|
||||
;
|
||||
else
|
||||
return 0;
|
||||
|
||||
Configuration cfg(Engine::configFile("tdmcard"));
|
||||
cfg.load();
|
||||
|
||||
const char* sectName = name.getValue(type);
|
||||
const char* sectName = name.getValue((circuit ? "voice" : "sig"),name.getValue("basename",name));
|
||||
NamedList* config = cfg.getSection(sectName);
|
||||
if (!config) {
|
||||
DDebug(&plugin,DebugWarn,"No section '%s' in configuration",c_safe(sectName));
|
||||
DDebug(&plugin,DebugAll,"No section '%s' in configuration",c_safe(sectName));
|
||||
return 0;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (plugin.debugAt(DebugAll)) {
|
||||
String tmp;
|
||||
name.dump(tmp,"\r\n ",'\'',true);
|
||||
Debug(&plugin,DebugAll,"TdmInterface::create %s%s",
|
||||
(circuit ? "span" : "interface"),tmp.c_str());
|
||||
}
|
||||
#endif
|
||||
NamedList dummy("general");
|
||||
NamedList* general = cfg.getSection("general");
|
||||
if (!general)
|
||||
|
@ -1717,18 +1725,15 @@ void* TdmInterface::create(const String& type, const NamedList& name)
|
|||
|
||||
|
||||
TdmInterface::TdmInterface(const NamedList& params)
|
||||
: m_device(TdmDevice::DChan,this,0,0),
|
||||
m_priority(Thread::Normal),
|
||||
m_errorMask(255),
|
||||
m_numbufs(16),
|
||||
m_bufsize(1024),
|
||||
m_buffer(0),
|
||||
m_readOnly(false),
|
||||
m_sendReadOnly(false),
|
||||
m_notify(0),
|
||||
m_timerRxUnder(0)
|
||||
: SignallingComponent(params),
|
||||
m_device(TdmDevice::DChan,this,0,0),
|
||||
m_priority(Thread::Normal),
|
||||
m_errorMask(255),
|
||||
m_numbufs(16), m_bufsize(1024), m_buffer(0),
|
||||
m_readOnly(false), m_sendReadOnly(false),
|
||||
m_notify(0),
|
||||
m_timerRxUnder(0)
|
||||
{
|
||||
setName(params.getValue("debugname","TdmInterface"));
|
||||
m_buffer = new unsigned char[m_bufsize];
|
||||
}
|
||||
|
||||
|
@ -1770,7 +1775,7 @@ bool TdmInterface::init(TdmDevice::Type type, unsigned int code, unsigned int ch
|
|||
{
|
||||
m_readOnly = getBoolValue("readonly",config,defaults,params);
|
||||
m_priority = Thread::priority(config.getValue("priority",defaults.getValue("priority")));
|
||||
int rx = params.getIntValue("rxunderruninterval");
|
||||
int rx = params.getIntValue("rxunderrun");
|
||||
if (rx > 0)
|
||||
m_timerRxUnder.interval(rx);
|
||||
int i = params.getIntValue("errormask",config.getIntValue("errormask",255));
|
||||
|
|
|
@ -223,7 +223,7 @@ class WpInterface : public SignallingInterface
|
|||
friend class WpSigThread;
|
||||
public:
|
||||
// Create an instance of WpInterface or WpSpan
|
||||
static void* create(const String& type, const NamedList& name);
|
||||
static SignallingComponent* create(const String& type, const NamedList& name);
|
||||
WpInterface(const NamedList& params);
|
||||
virtual ~WpInterface();
|
||||
// Initialize interface. Return false on failure
|
||||
|
@ -727,26 +727,32 @@ bool WpSocket::updateLinkStatus()
|
|||
* WpInterface
|
||||
*/
|
||||
// Create WpInterface or WpSpan
|
||||
void* WpInterface::create(const String& type, const NamedList& name)
|
||||
SignallingComponent* WpInterface::create(const String& type, const NamedList& name)
|
||||
{
|
||||
bool interface = false;
|
||||
if (type == "sig")
|
||||
if (type == "SignallingInterface")
|
||||
interface = true;
|
||||
else if (type == "voice")
|
||||
else if (type == "SignallingCircuitSpan")
|
||||
;
|
||||
else
|
||||
return 0;
|
||||
|
||||
Configuration cfg(Engine::configFile("wpcard"));
|
||||
cfg.load();
|
||||
const char* sectName = name.getValue(type);
|
||||
DDebug(&driver,DebugAll,"Factory trying to create %s='%s'",type.c_str(),sectName);
|
||||
const char* sectName = name.getValue((interface ? "sig" : "voice"),name.getValue("basename",name));
|
||||
NamedList* config = cfg.getSection(sectName);
|
||||
if (!config) {
|
||||
DDebug(&driver,DebugAll,"No section '%s' in configuration",c_safe(sectName));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (driver.debugAt(DebugAll)) {
|
||||
String tmp;
|
||||
name.dump(tmp,"\r\n ",'\'',true);
|
||||
Debug(&driver,DebugAll,"WpInterface::create %s%s",
|
||||
(interface ? "interface" : "span"),tmp.c_str());
|
||||
}
|
||||
#endif
|
||||
if (interface) {
|
||||
WpInterface* iface = new WpInterface(name);
|
||||
if (iface->init(*config,(NamedList&)name))
|
||||
|
@ -764,17 +770,17 @@ void* WpInterface::create(const String& type, const NamedList& name)
|
|||
}
|
||||
|
||||
WpInterface::WpInterface(const NamedList& params)
|
||||
: m_socket(this),
|
||||
m_thread(0),
|
||||
m_readOnly(false),
|
||||
m_notify(0),
|
||||
m_overRead(0),
|
||||
m_sendReadOnly(false),
|
||||
m_timerRxUnder(0),
|
||||
m_repeatCapable(s_repeatCapable),
|
||||
m_repeatMutex(true,"WpInterface::repeat")
|
||||
: SignallingComponent(params),
|
||||
m_socket(this),
|
||||
m_thread(0),
|
||||
m_readOnly(false),
|
||||
m_notify(0),
|
||||
m_overRead(0),
|
||||
m_sendReadOnly(false),
|
||||
m_timerRxUnder(0),
|
||||
m_repeatCapable(s_repeatCapable),
|
||||
m_repeatMutex(true,"WpInterface::repeat")
|
||||
{
|
||||
setName(params.getValue("debugname","WpInterface"));
|
||||
DDebug(this,DebugAll,"WpInterface::WpInterface() [%p]",this);
|
||||
}
|
||||
|
||||
|
@ -802,7 +808,7 @@ bool WpInterface::init(const NamedList& config, NamedList& params)
|
|||
int i = params.getIntValue("errormask",config.getIntValue("errormask",255));
|
||||
m_errorMask = ((i >= 0 && i < 256) ? i : 255);
|
||||
|
||||
int rx = params.getIntValue("rxunderruninterval");
|
||||
int rx = params.getIntValue("rxunderrun");
|
||||
if (rx > 0)
|
||||
m_timerRxUnder.interval(rx);
|
||||
|
||||
|
@ -1373,6 +1379,7 @@ bool WpSpan::init(const NamedList& config, const NamedList& defaults, NamedList&
|
|||
type = "E1";
|
||||
if (type == "E1") {
|
||||
m_chans = 31;
|
||||
m_increment = 32;
|
||||
if (cics.null())
|
||||
cics = "1-15,17-31";
|
||||
if (!m_samples)
|
||||
|
@ -1380,17 +1387,25 @@ bool WpSpan::init(const NamedList& config, const NamedList& defaults, NamedList&
|
|||
}
|
||||
else if (type == "T1") {
|
||||
m_chans = 24;
|
||||
m_increment = 24;
|
||||
if (cics.null())
|
||||
cics = "1-23";
|
||||
if (!m_samples)
|
||||
m_samples = 64;
|
||||
}
|
||||
else if (type == "BRI") {
|
||||
m_chans = 3;
|
||||
m_increment = 3;
|
||||
if (cics.null())
|
||||
cics = "1-2";
|
||||
if (!m_samples)
|
||||
m_samples = 80;
|
||||
}
|
||||
else {
|
||||
Debug(m_group,DebugNote,"WpSpan('%s'). Invalid voice group type '%s' [%p]",
|
||||
id().safe(),type.safe(),this);
|
||||
return false;
|
||||
}
|
||||
params.setParam("chans",String(m_chans));
|
||||
// Other data
|
||||
m_swap = defaults.getBoolValue("bitswap",true);
|
||||
m_noData = defaults.getIntValue("idlevalue",0xff);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -381,7 +381,7 @@ public:
|
|||
// Process incoming data
|
||||
virtual bool process();
|
||||
// Called by the factory to create Zaptel interfaces or spans
|
||||
static void* create(const String& type, const NamedList& name);
|
||||
static SignallingComponent* create(const String& type, const NamedList& name);
|
||||
protected:
|
||||
// Check if received any data in the last interval. Notify receiver
|
||||
virtual void timerTick(const Time& when);
|
||||
|
@ -1483,18 +1483,15 @@ bool ZapDevice::ioctl(IoctlRequest request, void* param, int level)
|
|||
* ZapInterface
|
||||
*/
|
||||
ZapInterface::ZapInterface(const NamedList& params)
|
||||
: m_device(ZapDevice::DChan,this,0,0),
|
||||
m_priority(Thread::Normal),
|
||||
m_errorMask(255),
|
||||
m_numbufs(16),
|
||||
m_bufsize(1024),
|
||||
m_buffer(0),
|
||||
m_readOnly(false),
|
||||
m_sendReadOnly(false),
|
||||
m_notify(0),
|
||||
m_timerRxUnder(0)
|
||||
: SignallingComponent(params),
|
||||
m_device(ZapDevice::DChan,this,0,0),
|
||||
m_priority(Thread::Normal),
|
||||
m_errorMask(255),
|
||||
m_numbufs(16), m_bufsize(1024), m_buffer(0),
|
||||
m_readOnly(false), m_sendReadOnly(false),
|
||||
m_notify(0),
|
||||
m_timerRxUnder(0)
|
||||
{
|
||||
setName(params.getValue("debugname","ZapInterface"));
|
||||
m_buffer = new unsigned char[m_bufsize + ZAP_CRC_LEN];
|
||||
XDebug(this,DebugAll,"ZapInterface::ZapInterface() [%p]",this);
|
||||
}
|
||||
|
@ -1507,27 +1504,31 @@ ZapInterface::~ZapInterface()
|
|||
}
|
||||
|
||||
// Called by the factory to create Zaptel interfaces or spans
|
||||
void* ZapInterface::create(const String& type, const NamedList& name)
|
||||
SignallingComponent* ZapInterface::create(const String& type, const NamedList& name)
|
||||
{
|
||||
bool circuit = true;
|
||||
if (type == "sig")
|
||||
if (type == "SignallingInterface")
|
||||
circuit = false;
|
||||
else if (type == "voice")
|
||||
else if (type == "SignallingCircuitSpan")
|
||||
;
|
||||
else
|
||||
return 0;
|
||||
|
||||
Configuration cfg(Engine::configFile("zapcard"));
|
||||
cfg.load();
|
||||
|
||||
const char* sectName = name.getValue(type);
|
||||
DDebug(&plugin,DebugAll,"Factory trying to create %s='%s'",type.c_str(),sectName);
|
||||
const char* sectName = name.getValue((circuit ? "voice" : "sig"),name.getValue("basename",name));
|
||||
NamedList* config = cfg.getSection(sectName);
|
||||
if (!config) {
|
||||
DDebug(&plugin,DebugAll,"No section '%s' in configuration",c_safe(sectName));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (plugin.debugAt(DebugAll)) {
|
||||
String tmp;
|
||||
name.dump(tmp,"\r\n ",'\'',true);
|
||||
Debug(&plugin,DebugAll,"ZapInterface::create %s%s",
|
||||
(circuit ? "span" : "interface"),tmp.c_str());
|
||||
}
|
||||
#endif
|
||||
String sDevType = config->getValue("type");
|
||||
ZapDevice::Type devType = (ZapDevice::Type)lookup(sDevType,s_types,ZapDevice::E1);
|
||||
|
||||
|
@ -1601,7 +1602,7 @@ bool ZapInterface::init(ZapDevice::Type type, unsigned int code, unsigned int ch
|
|||
m_device.channel(channel,code);
|
||||
m_readOnly = getBoolValue("readonly",config,defaults,params);
|
||||
m_priority = Thread::priority(config.getValue("priority",defaults.getValue("priority")));
|
||||
int rx = params.getIntValue("rxunderruninterval");
|
||||
int rx = params.getIntValue("rxunderrun");
|
||||
if (rx > 0)
|
||||
m_timerRxUnder.interval(rx);
|
||||
int i = params.getIntValue("errormask",config.getIntValue("errormask",255));
|
||||
|
@ -1814,16 +1815,19 @@ bool ZapSpan::init(ZapDevice::Type type, unsigned int offset,
|
|||
if (!voice)
|
||||
voice = "1-15.17-31";
|
||||
chans = 31;
|
||||
m_increment = 32;
|
||||
break;
|
||||
case ZapDevice::T1:
|
||||
if (!voice)
|
||||
voice = "1-23";
|
||||
chans = 24;
|
||||
m_increment = 24;
|
||||
break;
|
||||
case ZapDevice::BRI:
|
||||
if (!voice)
|
||||
voice = "1-2";
|
||||
chans = 3;
|
||||
m_increment = 3;
|
||||
break;
|
||||
case ZapDevice::FXO:
|
||||
case ZapDevice::FXS:
|
||||
|
@ -1848,8 +1852,7 @@ bool ZapSpan::init(ZapDevice::Type type, unsigned int offset,
|
|||
}
|
||||
|
||||
if (!digital)
|
||||
chans = count;
|
||||
((NamedList*)¶ms)->setParam("chans",String(chans));
|
||||
m_increment = chans = count;
|
||||
unsigned int start = params.getIntValue("start",0);
|
||||
|
||||
// Create and insert circuits
|
||||
|
|
Loading…
Reference in New Issue