Compare commits

...

75 Commits

Author SHA1 Message Date
Admin Commit
533b3bde8a Importing release summary for 1.4.14 release.
git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.4.14@2314 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2012-12-20 16:46:58 +00:00
Admin Commit
47b2ff8860 Importing files for 1.4.14 release.
git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.4.14@2313 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2012-12-20 16:46:52 +00:00
Admin Commit
782a08d0e1 Creating tag for the release of libpri-1.4.14
git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.4.14@2312 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2012-12-20 16:46:03 +00:00
Richard Mudgett
28553ff8cb Handle optional Recommendation octet 3a in Cause IE.
If the MSB of octet 3 is 0 then the optional Recommendation octet 3a is
present.

References: ITU-T Q.850 Section 2.1 and ETSI ETS 300 102-1 Section 4.5.12.

(closes issue PRI-151)
Reported by: Tzafrir Cohen
Patches:
      0001-handle-optional-Recommendation-in-Cause-IE.patch (license #5035) patch uploaded by Tzafrir Cohen
      Modified


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2310 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2012-12-10 18:28:55 +00:00
Richard Mudgett
1a0927ca23 Q.SIG: Allow PROGRESS when in the Active state.
ECMA-143 Section 10.1.7.2 indicates that PROGRESS is allowed when in the
Active state.

* Made Q.SIG ignore the PROGRESS message when in the Active call state.

(closes issue PRI-147)
Reported by: Nick Merrett


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2308 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2012-11-13 19:59:50 +00:00
Richard Mudgett
de78c8d37f Fix compiler error with ALERTING_NO_PROGRESS define.
git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2307 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2012-11-13 19:42:17 +00:00
Richard Mudgett
cdb844c16b Fix compiler warning in pritest.c.
* Made do_channel() exit on a failed write().

(closes issue PRI-145)
Reported by: Tzafrir Cohen
Patches:
      fix_unused_write.patch (license #5035) patch uploaded by Tzafrir Cohen
      Modified


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2305 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2012-10-29 21:19:52 +00:00
Richard Mudgett
75bf8f0a20 Allow passing compiler flags (CFLAGS, LDFLAGS)
(closes issue PRI-144)
Reported by: Tzafrir Cohen
Patches:
      flags.diff (license #5035) patch uploaded by Tzafrir Cohen


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2300 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2012-09-26 15:46:23 +00:00
Richard Mudgett
5e3581c977 Fix compile error in pridump.c.
With gcc 4.6.3 it's possible to get the following error:

  $ make
  gcc -Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g -fPIC  -O2  -MD -MT pridump.o -MF .pridump.o.d -MP -c -o pridump.o pridump.c
  pridump.c: In function \u2018pri_bridge\u2019:
  pridump.c:117:1: error: no return statement in function returning non-void [-Werror=return-type]
  cc1: all warnings being treated as errors
  make: *** [pridump.o] Error 1

Changing the function return value to void fixes the issue since there
were no places in the code that used the return value.

(closes issue PRI-143)
Reported by: Birger "WIMPy" Harzenetter
Patches:
      0001-Fix-no-return-statement-in-function-returning-non-vo.patch (license #5417) patch uploaded by Shaun Ruffell


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2298 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2012-09-10 15:52:31 +00:00
Richard Mudgett
d9c6cc68a5 SVN ignore built utilities.
git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2295 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2012-08-11 01:38:57 +00:00
Richard Mudgett
27808e3640 * Made no longer compile *.lo files they are identical to *.o files.
* Made compile the pritest, rosetest, and testprilib utilities using the
static libpri library.  No more forgetting to install the library after a
change and wondering why it still did not work.  The pridump utility is
still dynamically linked.

* Made compile the utilities by default.


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2294 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2012-08-11 01:37:58 +00:00
Richard Mudgett
4af121db62 Make pridump and testprilib compile again.
git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2292 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2012-08-11 00:42:04 +00:00
Richard Mudgett
053a38202e Removed MDL/TEI management configuration warning message.
Some telco switches send out MDL messages even though they are configured
for PTP.  Usually they are checking for assigned TEI's.  Since these
switches periodically poll for assigned TEI's, the message needlessly
fills up log files.

* Changed message warning level to a normal debug message level and
reworded.

(closes issue PRI-137)
Reported by: Bart Coninckx


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2290 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2012-07-30 16:20:47 +00:00
Richard Mudgett
fffb7babaf Implement T316 to allow RESTART messages to be automatically retransmitted.
Q.931 defines the T316 timer to retransmit RESTART messages if a RESTART
ACKNOWLEDGE message is not received before the timer expires.  Q.931
defaults the time of T316 to 2 minutes with the default number of
consecutive RESTART failures as two.

* To support legacy behavior, the T316 timer is disabled by default.  It
is also disabled because the user cannot configure it to disabled if it is
enabled.

* The N316 count is created to allow the number of RESTART attempts to be
configurable.  Note you will need to recompile Asterisk to be able to
configure N316.

(issue ASTERISK-19608)
(issue AST-815)
(closes issue PRI-133)
Reported by: Mike Boylan
Tested by: rmudgett


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2288 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2012-06-28 00:16:33 +00:00
Richard Mudgett
f78400fc07 Make pri_pres2str() return correct string.
* Fix pri_pres2str() mask creation.

(closes issue PRI-139)
Reported by: Pavel Troller
Patches:
      q931.c.diff (license #6302) patch uploaded by Pavel Troller


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2286 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2012-05-14 14:54:01 +00:00
Richard Mudgett
a7eaec1aaa Make number not available presentation also set screening to network provided.
Q.951 indicates that when the presentation indicator is "Number not
available due to interworking" for a number then the screening indicator
field should be "Network provided".

Released versions of Asterisk starting with v1.8 relesed before this patch
only recognized the PRES_NUMBER_NOT_AVAILABLE value as an unavailable
number.  This patch improves compatibility as a result.

* Made mask the presentation value for names and numbers from the upper
layer.

* Made pri_mwi_indicate_v2() also call q931_party_id_fixup() for
completeness even though it is a noop in this case.

* Made pri_pres2str() deceoode better.


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2284 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2012-03-23 19:35:23 +00:00
Kinsey Moore
17649b363b Make PRI_DEBUG_Q921_RAW work independantly of PRI_DEBUG_Q921_DUMP
Ensure that the DUMP and RAW flags work independently in q921_dump().

(closes issue PRI-119)
Patch-by: wimpy


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2282 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2012-02-03 23:12:57 +00:00
Richard Mudgett
2c159d4685 Use ie2str(full_ie) where possible in q931.c.
Initial patch by Alec Davis.

Review: https://reviewboard.asterisk.org/r/1633/


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2280 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2012-01-26 20:19:50 +00:00
Richard Mudgett
6078b21698 Remove nul octets from IE data that is normally treated as strings.
Sometimes ie values received from carriers contain nul octets in values
normally treated by libpri as nul terminated strings.  A discussion on the
asterisk-users list determined that the best thing to do in the situation
is to delete the nul octets and unconditionally report/log when that
happens.

* Remove nul octets from the following ie's and generate an unconditional
log message to the upper layer when they are removed:
Connected Number
Connected Address
Redirecting Number
Original Called Number
Redirection Number
Called Party Number
Calling Party Number
Display
Keypad Facility

(closes issue PRI-128)
Reported by: phsultan
Patches:
      jira_pri_128.patch (license #5621) patch uploaded by rmudgett (modified)
Tested by: rmudgett


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2278 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2011-12-16 20:01:46 +00:00
Richard Mudgett
4e7c3d1462 Implement handling a multi-channel RESTART request.
The channel id ie can supply a slotmap or list of channels.  For a RESTART
message, this can be handy to indicate multiple channels that need to be
restarted at the same time.

An incoming RESTART request will now generate a PRI_EVENT_RESTART to the
upper layer for each channel indicated in the request.  If the event is
successfully generated for all indicated channels then a
RESTART_ACKNOWLEDGE is sent back to the peer indicating all channels
restarted.

* Add the ability to process a channel id ie channel list with a RESTART
request.

* Add the ability to process slotmaps with a RESTART request.

(closes issue PRI-93)
Reported by: Marcin Kowalczyk
Patches:
      jira_pri_93.patch (license #5621) patch uploaded by rmudgett
Tested by: zvision, rmudgett

(closes issue PRI-71)
Reported by: Torrey Searle
Tested by: rmudgett


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2277 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2011-12-16 19:26:56 +00:00
Richard Mudgett
5947536965 Fix message typo: Weird
(closes issue PRI-126)
Reported by: Tzafrir Cohen


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2275 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2011-09-26 22:54:46 +00:00
Richard Mudgett
c5ec479bd2 Outgoing BRI calls fail when using Asterisk 1.8 with HA8, HB8, and B410P cards.
France Telecom brings layer 2 and layer 1 down on BRI lines when the line
is idle.  When layer 1 goes down Asterisk cannot make outgoing calls and
the HA8 and HB8 cards also get IRQ misses.

The inability to make outgoing calls is because the line is in red alarm
and Asterisk will not make calls over a line it considers unavailable.
The IRQ misses for the HA8 and HB8 card are because the hardware is
switching clock sources from the line which just brought layer 1 down to
internal timing.

There is a DAHDI option for the B410P card to not tell Asterisk that layer
1 went down so Asterisk will allow outgoing calls: "modprobe wcb4xxp
teignored=1".  There is a similar DAHDI option for the HA8 and HB8 cards:
"modprobe wctdm24xxp bri_teignored=1".  Unfortunately that will not clear
up the IRQ misses when the telco brings layer 1 down.

* Add layer 2 persistence option to customize the layer 2 behavior on BRI
PTMP lines.  The new option has three settings: 1) Use libpri default
layer 2 setting.  2) Keep layer 2 up.  Bring layer 2 back up when the peer
brings it down.  3) Leave layer 2 down when the peer brings it down.
Layer 2 will be brought up as needed for outgoing calls.

(issue AST-598)
Reported by: Trey Blancher


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2273 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2011-08-17 15:48:54 +00:00
Richard Mudgett
092811da55 Option needed for Q931_IE_TIME_DATE to be optional in CONNECT message.
The NEC SV8300 rejects the Q931_IE_TIME_DATE for Q.SIG.

Add option to specify if and how much of the current time is put in
Q931_IE_TIME_DATE.
* Send date/time ie never.
* Send date/time ie date only.
* Send date/time ie date and hour.
* Send date/time ie date, hour, and minute.
* Send date/time ie date, hour, minute, and second.
* Send date/time ie default: Libpri will send date and hhmm only when in
NT PTMP mode to support ISDN phones.

(closes issue #19221)
Reported by: kenner

JIRA SWP-3396


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2266 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2011-05-17 20:13:10 +00:00
Richard Mudgett
239f8186ef Problems with ISDN MWI to phones.
1) The "controlling user number" is always the number of the voice mail box
which is identical with the subscriber number itself.  This number which
is listed in the ISDN phone MWI menu cannot be called back to contact the
voice mail box.  The controlling user number should be made configurable.

2) The MWI indication is not restricted to a user (broadcast facility with
dummy call reference).  A called party IE should be added to address only
the relevant MSN.  (ETSI 300-196 Section 8.3.2.4)

JIRA ABE-2738
JIRA SWP-2846


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2262 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2011-04-18 19:43:47 +00:00
Richard Mudgett
c794af652e CallRerouting response not sent if peer hangs up first.
Send the CallRerouting response on the next message instead of only on the
DISCONNECT message.  The next message is either going to be a DISCONNECT
or RELEASE depending on who initiates disconnection first.


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2258 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2011-03-18 01:59:18 +00:00
Richard Mudgett
1013e7626d Implement the mandatory T312 timer for NT PTMP broadcast SETUP calls.
* Fixed stopping T303 too early on a NT PTMP broadcast SETUP call if a
subcall just receives a RELEASE_COMPLETE(busy).

* Fixed a valgrind reported invalid read/write when hanging up a NT PTMP
broadcast SETUP call.

JIRA LIBPRI-32
JIRA SWP-2548


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2238 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2011-03-01 00:50:04 +00:00
Richard Mudgett
afd91f7f31 Miscellaneous cleanup before T312 branch merge.
git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2236 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2011-03-01 00:22:38 +00:00
Richard Mudgett
a5efd98835 Fix valgrind reported invalid read/write for display text feature.
git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2233 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2011-02-28 23:39:30 +00:00
Richard Mudgett
898bc57fce Improve the usefulness of pri_dump_info_str() output.
* Add BRI and PTMP strings to node type config when configured that way.
* Move Q.921 statistics to after configuration settings.
* Add call and cc_record debug statistics to pri_dump_info_str().


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2232 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2011-02-28 23:20:25 +00:00
Richard Mudgett
9effbfc130 Add determined remote node type to pri_dump_info_str().
git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2227 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2011-02-28 20:58:41 +00:00
Richard Mudgett
e7a5d0da62 B channel lost by incoming call in BRI NT PTMP mode.
A phone's RELEASE_COMPLETE as a response to an initial broadcast SETUP
blocks one B channel permantly when the call is cancelled.

Scenario: A call to the ISDN Bus is acknowledged (ALERTING) by one
phone/endpoint and rejected by another phone/endpoint with a
RELEASE_COMPLETE.  The call is then cancelled by the caller.  If the whole
procedure is repeated once again then any further call attempt is rejected
(WARNING[5666]: app_dial.c:1546 dial_exec_full: Unable to create channel
of type 'DAHDI' (cause 34 - Circuit/channel congestion)).  It seems that
receiving a RELEASE_COMPLETE in that state blocks one B channel
permanently when the call is cancelled by the caller.

Background: The ISDN phones (Siemens Gigaset 3035 or CX253) we use for
testing additionally contain a DECT base station, which operates as a
different endpoint on the ISDN Bus (TEI).  If the DECT base station is not
in use then there are no DECT phones registered to the base station.  The
DECT base station responds to an incoming call not directed toward it with
(RELEASE_COMPLETE, cause: no user responding).

* Made initiate_hangup_if_needed() also hangup the subcall if it is in the
NULL state.

* Simplified q931_set_subcall_winner().

JIRA ABE-2745
JIRA SWP-2954


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2207 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2011-02-17 21:12:04 +00:00
Richard Mudgett
df22f0e1cb DMS-100 not receiving caller name anymore.
Looks like DMS-100 is using the same message as Q.SIG to receive the
caller name.

Add the ability to decode the ROSE calling name message defined for the
Q.SIG switch on the DMS-100 switch.

(closes issue #18822)
Reported by: cmorford
Patches:
      issue18822_v1.4.patch uploaded by rmudgett (license 664)
Tested by: cmorford


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2206 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2011-02-17 20:35:01 +00:00
Richard Mudgett
492a19ab7d * Added switchtype to ROSE invoke operation not handled message.
* Reordered NI2 ROSE message table so any conflicts with the pirated Q.SIG
messages will be in favor of the NI2 specific messages.  This is
precautionary only.


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2204 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2011-02-17 17:50:20 +00:00
Richard Mudgett
2867fc717e Crash if NFAS swaps D channels on a call with an active timer.
If a Q.931 call record related timer is started on one NFAS D channel
expires after NFAS swaps to another D channel, then libpri could crash.

For example:
1) Hangup a call.
1a) Send a DISCONNECT.
1b) Start the T305 retransmit timer on the current D channel.
2) The RELEASE comes in on another D channel.
2a) The found call record switches its assignment to the new D channel.
2b) Attempt to stop T305.  Unfortunately, the timer was started on another
    D channel so the attempt does not find the timer to stop.
3) The hangup sequence continues normally and the call record is freed
   since there is only one call record pool.
4) T305 expires on the original D channel and crashes the system when it
   uses the stale call record pointer it has saved.

Made each D channel timer pool have a unique range of valid timer
identifiers.  If a given timer identifier is not in the range for the
current NFAS D channel, then search the D channel group for the original D
channel.

JIRA LIBPRI-58
JIRA SWP-2721


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2202 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2011-02-16 19:23:02 +00:00
Richard Mudgett
d1cac6352a Fix I-frame retransmission quirks.
Revamped the I-frame retransmission queue to better comply with Q.921:
Figure B.7/Q.921 (sheet 1 of 10) and Figure B.9/Q.921 (Sheet 5 of 5).  The
changes prevent retransmitting I-frames when the peer is busy (RNR) (Q.921
Section 5.6.5) and eliminate an unnecessary delay sending new I-frames
after an I-frame retransmission.

Related to JIRA LIBPRI-60


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2200 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2011-02-14 23:33:56 +00:00
Richard Mudgett
e01dce27b7 Swap of master/slave in pri_enslave() incorrect.
Thank you.  All I can say is oops.

(closes issue #18769)
Reported by: jcollie
Patches:
      libpri-1.4.12-beta3-swap.patch uploaded by jcollie (license 412)


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2192 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2011-02-08 16:44:37 +00:00
Richard Mudgett
ed0d76d538 Add display ie text handling options.
The display ie handling can be controlled independently in the send and
receive directions with the following options:

* Block display text data.

* Use display text in SETUP/CONNECT messages for name.

* Use display text for COLP name updates (FACILITY/NOTIFY as appropriate).

* Pass arbitrary display text during a call.  Sent in INFORMATION
messages.  Received from any message that the display text was not used as
a name.

If the display options are not set then the options default to legacy
behavior.


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2190 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2011-02-04 19:59:45 +00:00
Richard Mudgett
d0dbd5b3f2 Add Q931_IE_TIME_DATE to CONNECT message when in network mode.
Add the Q931_IE_TIME_DATE with the current date/time of the system to the
Q.931 CONNECT message when in network mode.  The date/time IE allows
attached equipment to synchronize their clock with the network.  Most
notably, ISDN phones can display the current date/time.

See issue #18047 about a concern with non-conforming Siemens terminals.

(closes issue #18047)
Reported by: wuwu
Patches:
      timedate.patch uploaded by rmudgett (license 664)
Tested by: rmudgett

JIRA SWP-2955
JIRA ABE-2747


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2187 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2011-02-04 18:09:46 +00:00
Richard Mudgett
82a0a8e2ab Enable LIBPRI_COUNTERS code by default.
Removed the conditional LIBPRI_COUNTERS to include the code
unconditionally.

Patches:
      enable_LIBPRI_COUNTERS_LIBPRI-61.diff uploaded by jbigelow

JIRA LIBPRI-61


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2183 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2011-02-01 00:37:49 +00:00
Richard Mudgett
261ab22dda Invalid PTMP redirecting signaling as TE towards NT.
* The PTMP redirection signaling (NOTIFY redirection number and
notification code, SETUP redirecting number) is also sent in PTMP/TE mode.
It should only apply in PTMP/NT mode.  The call setup proceeds but the
network (Deutsche Telekom) reacts with ugly ISDN STATUS messages.

* Don't send the redirecting number ie when PTP is also sending the
DivertingLegInformation2 facility.  The redirecting number ie is redundant
and the network (Deutsche Telekom) complains about it.

JIRA LIBPRI-53
JIRA SWP-2543


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2175 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-12-21 19:46:14 +00:00
Richard Mudgett
1b32a0e31b Fix Q.931 retried SETUP not sending facility ies.
Resend standard facility ies when the SETUP is retried by Q.931.  However,
one time facility ies are no longer available to add to a retried SETUP
message.


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2174 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-12-21 19:41:52 +00:00
Richard Mudgett
19e2a84c89 Add call transfer exchange of subaddresses support and fix PTMP call transfer signaling.
* Add the ability to exchange subaddresses for ETSI PTMP, ETSI PTP, and
Q.SIG for call transfer.

* Fix ETSI PTMP to send the correct messages depending on the call state
for call transfer.  NOTE: Some ISDN phones only handle the NOTIFY message
that the EN 300-369 spec says should be sent only if the call has not
connected yet.

JIRA LIBPRI-47
JIRA SWP-2363

Review:	https://reviewboard.asterisk.org/r/1051/


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2172 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-12-21 16:49:30 +00:00
Richard Mudgett
4faa2935f8 Better HOLD/RETRIEVE collision handling.
The upper layer is now initiating HOLD/RETRIEVE signaling.  These changes
are needed to help preserve the correct channel id after a collision.


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2170 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-12-20 23:12:10 +00:00
Richard Mudgett
8dc9486287 Fix regression when reorganized for struct pri and struct q921_link.
git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2169 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-12-20 22:42:07 +00:00
Richard Mudgett
cea6d541df Return error if q931_notify() cannot send NOTIFY.
git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2167 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-12-14 01:09:57 +00:00
Richard Mudgett
b79b886fc4 Fix bizarre logic to work as originally intended in q931_notify().
In revision 238: Don't allow notification codes outside of the Q.931 spec
for switches other than EuroISDN.


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2166 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-12-14 00:55:49 +00:00
Richard Mudgett
517e5ac5ce Asterisk is getting a "No D-channels available!" warning message every 4 seconds.
For PTP links, libpri generated the PRI_EVENT_DCHAN_DOWN event every time
it failed to bring layer 2 up because the physical layer is down.

For PTP links, made generate the PRI_EVENT_DCHAN_UP/PRI_EVENT_DCHAN_DOWN
only when it enters/exits the Q.921 superstate consisting of states
7(Q921_MULTI_FRAME_ESTABLISHED) and 8(Q921_TIMER_RECOVERY).

Also changed the PTP link restart delay to be link specific instead of D
channel specific because the GR-303 PTP switch types have more than one
Q.921 link.

(closes issue #17270)
Reported by: jmls


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2113 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-11-12 02:31:24 +00:00
Richard Mudgett
12805eb71f SABME flood on backup D-channel in NFAS configuration.
Made delay restarting the PTP layer 2 link by the T200 time instead of
immediately.  Q.921 does not specify any particular time to restart the
layer 2 link.  Q.921 leaves it up to the upper layers to decide when or if
another attempt to bring layer 2 up is made.  Earlier versions of libpri
used the T200 time to restart the link.

This is a reimplementaion of -r1878.

(closes issue #18255)
Reported by: bklang

JIRA SWP-2508


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2111 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-11-11 00:30:33 +00:00
Richard Mudgett
d2984ee7eb Minor MDL handler changes.
* Clear mdl_error in case we could not schedule the handler callback.

* Change MDL handlers to not return the handled state since the caller did
not care.


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2109 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-11-10 23:47:45 +00:00
Richard Mudgett
230e2d9013 Added TEI identity check feature to reclaim dead TEIs.
This is the new feature portion of JIRA LIBPRI-51/SWP-2453.


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2105 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-11-05 20:05:25 +00:00
Richard Mudgett
de0bf0b50e Q.921 TEI assignment procedure corrections.
* We should send the TEI identity denied message with TEI=127 when the TEI
pool is exhausted.

* We should remove our TEI if we see a TEI identity assign message
assigning our TEI to someone else.


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2104 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-11-05 19:59:45 +00:00
Richard Mudgett
f7866a2de8 Convert TEI identity defines to enum and create 2str() function.
git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2103 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-11-05 19:48:00 +00:00
Richard Mudgett
8db67a915d Remove unneeded struct q921_link.mdl_error_state member.
git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2102 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-11-05 19:35:15 +00:00
Richard Mudgett
948625318a Remove all TEIs when NT PTMP starts.
Remove all TEIs when a NT PTMP link is started and there are no other
links to make sure there are no devices that think they have a TEI.  A
device may think it has a TEI if the upper layer program is restarted or
the system reboots.

This fixes the bug portion of JIRA LIBPRI-51/SWP-2453.


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2101 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-11-05 19:24:01 +00:00
Richard Mudgett
69694554fb Mainly put space after switch and while keywords.
git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2098 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-11-05 19:02:42 +00:00
Richard Mudgett
33aafe9b5a B410P gets incoming call packets on ISDN but Asterisk doesn't see the call.
The Cisco 1751 with VIC 2-BRI ports sends out SETUP messages on the
broadcast TEI as if the BRI were PTMP even though it is configured for PTP
mode.

Make PTP mode also accept frames on SAPI=0, TEI=127 (Broadcast).

(closes issue #18232)
Reported by: lelio
Patches:
      issue18232_v1.4.patch uploaded by rmudgett (license 664)
Tested by: lelio


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2088 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-11-02 19:11:01 +00:00
Richard Mudgett
7f55b600e0 Fixes CC agents not automatically clearing if T309 clears the original call.
Incoming calls with CC enabled will not automatically clear the CC offer
record when the call is aborted by T309 processing.  All CC agent FSM's
have this problem (PTMP, PTP, and Q.SIG).

To reproduce:
1) Place incoming call to Asterisk/libpri
2) Either before or after the call is answered, bring the ISDN link down.
3) T309 processing, T309 timeout, or TEI removal will leave the CC agent
FSM in the CC available state.

The problem is indicated by the "cc report status" CLI command showing a
status of CC offered to caller but it will never timeout.

The FSM's can be manually cleared by using the "cc cancel all" or "cc
cancel core" CLI commands.

JIRA LIBPRI-46
JIRA SWP-2241


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2079 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-10-21 18:00:03 +00:00
Richard Mudgett
5923df047d Partial support for dynamic interfaces with NFAS.
To have some support for dynamic interfaces, the master NFAS D channel
control structure will always exist even if it is abandoned/deleted by the
upper layer.  The master/slave pointers ensure that the correct master
will be used.


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2078 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-10-21 17:32:39 +00:00
Richard Mudgett
f9c3c8d026 Extract the layer 2 link structure out of struct pri.
This completes the layer 2 link and Q.931 call control restructuring.
Some code is now simplified since there is only one D channel control
structure and the amount of allocated memory is reduced.


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2077 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-10-21 17:30:41 +00:00
Richard Mudgett
53c142990f Restructure the Q.931 call record to layer 2 link association.
This is in anticipation of extracting a layer 2 link structure out of
struct pri.

Also completes fixing timer value access for the rest of libpri.  The
timer access must always be on the D channel control structure (Master).

May have fixed some events from timeouts not being passed to the upper
layer.  The timeout events must always be on the D channel control
structure (Master).


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2070 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-10-21 16:37:10 +00:00
Richard Mudgett
cd588eccce Logically separate Q.921 TEI link processing from D channel control.
This is in anticipation of extracting a layer 2 link structure out of
struct pri.

Also fixes Q.921 timer value access.  The timer access must always be on
the D channel control structure (Master).


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2063 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-10-21 16:14:54 +00:00
Richard Mudgett
cf456d41e2 Dump Q.931 message using the TEI value the message came in with.
git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2042 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-10-16 04:34:39 +00:00
Richard Mudgett
31b4b63b40 Create two versions of call ptr verify. One gripes and one does not.
git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2027 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-10-15 16:39:10 +00:00
Richard Mudgett
fb61cedfd7 Crash when receiving an unknown/unsupported message type.
Fix double free of a call record and the subsequent continued use of the
freed call record when receiving an unsupported/unknown message type.

(closes issue #17968)
Reported by: gelo
Patches:
      issue_17968_v1.4.patch uploaded by rmudgett (license 664)


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2021 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-10-14 18:35:48 +00:00
Richard Mudgett
2045db6a69 Segfault in pri_schedule_del() - ctrl value is invalid.
Validate the given call pointer in libpri API calls.  If the call pointer
is not an active call record then a complaint message is issued and the
API call aborts.  The call pointer is likely stale.

This patch is defensive.  More information is needed to figure out why
Asterisk still has a call pointer during its hangup sequence.

(closes issue #17522)
(closes issue #18032)
Reported by: schmoozecom
Patches:
      issue_18032_v1.4.patch uploaded by rmudgett (license 664)
Tested by: rmudgett


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2015 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-10-14 17:09:40 +00:00
Tilghman Lesher
21638280af Minor changes to make libpri build on Mac OS X
git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2009 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-10-07 04:00:04 +00:00
Russell Bryant
ae11fcd0e6 Makefile tweaks to allow building for code coverage analysis.
git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2001 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-09-16 21:24:40 +00:00
Richard Mudgett
384ae1e688 PRI links do not retain active calls if the link comes back before T309 expires.
The DL-ESTABLISH confirm event was not passed from Q.921 to Q.931 so Q.931
never cancelled the T309 timer.

Refactored q931_dl_tei_removal() and q931_dl_indication() into
q931_dl_event() to allow the DL-ESTABLISH confirm/indication and
DL-RELEASE confirm/indication events to be passed to Q.931.


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1991 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-09-13 21:21:37 +00:00
Richard Mudgett
05158ec5fb BRI PTMP: Active channels not cleared when the interface goes down.
If the connection to the terminal is lost while there are open channels
on the interface, red alarm is reported, but the open channels are never
cleared.  Additionally, if you manually try to channel request hangup,
Asterisk crashes.

For PTMP, the T309 processing was not searching the call pool on the
master control record.  Additionally, for NT PTMP, the timeout events were
not passed to the upper layer because the events were not put on the
master control record where timer processing expects them.

(closes issue #17865)
Reported by: wimpy
Patches:
      issue17865_v1.4.patch uploaded by rmudgett (license 664)
Tested by: rmudgett, wimpy


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1982 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-09-13 16:07:24 +00:00
Richard Mudgett
0c79b0a4b1 Fix spelling error in PTMP agent FSM files.
git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1976 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-09-10 23:15:01 +00:00
Richard Mudgett
e0f4da2773 Added more parameter checks to pri_set_timer() and pri_get_timer().
Made pri_dump_info_str() output a line for each Q.921 TEI Tx queue when
LIBPRI_COUNTERS is defined.


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1965 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-09-08 21:43:14 +00:00
Richard Mudgett
c20f34992a Made Q.921 delay events to Q.931 if the event could immediately generate response frames.
Q.921 was passing a q931_dl_indication(up) event to Q.931 before it was
finished processing the frame.  The q931_dl_indication(up) event could
immediately send STATUS messages in the Q.921 intermediate state that
would then get stuck in the tx queue with an invalid N(S).

Q.921 was passing i-frames to Q.931 before it was finished processing the
frame.  The i-frames could cause Q.931 to immediately generate a response
message that may cause the peer to see the P/F bit as incorrect.

Delayed passing q931_dl_indication(up) events and i-frames to Q.931 until
Q.921 has completed processing the frame event.  (The Q.921 SDL diagrams
were designed with this assumption.)

(closes issue #17360)
Reported by: shawkris
Patches:
      issue17360_v1.4.patch uploaded by rmudgett (license 664)
Tested by: shawkris, rmudgett


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1962 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-09-08 00:13:24 +00:00
Richard Mudgett
ad998f6f64 Prevent a CONNECT message from sending a CONNECT ACKNOWLEDGE in the wrong state.
Filter the processing of the CONNECT message to prevent libpri from
sending a CONNECT ACKNOWLEDGE when the call is in an inappropriate state.
This can happen when we hang up an outgoing call after the other end has
sent a CONNECT but before we have processed the CONNECT.

(issue #17360)
Reported by: shawkris
Patches:
      issue17360_con_ack_v1.4.patch uploaded by rmudgett (license 664)


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1961 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-09-08 00:10:05 +00:00
Richard Mudgett
4011816ead Balance curly braces in post_handle_q931_message().
git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1958 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-09-07 23:13:04 +00:00
Richard Mudgett
34370a5984 Don't crash in __pri_new_tei() if a GR303 subchannel creation fails.
git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1955 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-09-02 17:33:51 +00:00
27 changed files with 7879 additions and 2233 deletions

1
.version Normal file
View File

@@ -0,0 +1 @@
1.4.14

1993
ChangeLog Normal file

File diff suppressed because it is too large Load Diff

101
Makefile
View File

@@ -10,23 +10,20 @@
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#
# Uncomment if you want libpri not send PROGRESS_INDICATOR w/ALERTING
#ALERTING=-DALERTING_NO_PROGRESS
# Uncomment if you want libpri to count number of Q921/Q931 sent/received
#LIBPRI_COUNTERS=-DLIBPRI_COUNTERS
CC=gcc
GREP=grep
AWK=awk
@@ -68,37 +65,23 @@ STATIC_OBJS= \
rose_qsig_name.o \
version.o
DYNAMIC_OBJS= \
copy_string.lo \
pri.lo \
q921.lo \
prisched.lo \
q931.lo \
pri_aoc.lo \
pri_cc.lo \
pri_facility.lo \
asn1_primitive.lo \
rose.lo \
rose_address.lo \
rose_etsi_aoc.lo \
rose_etsi_cc.lo \
rose_etsi_diversion.lo \
rose_etsi_ect.lo \
rose_etsi_mwi.lo \
rose_other.lo \
rose_q931.lo \
rose_qsig_aoc.lo \
rose_qsig_cc.lo \
rose_qsig_ct.lo \
rose_qsig_diversion.lo \
rose_qsig_mwi.lo \
rose_qsig_name.lo \
version.lo
CFLAGS=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g -fPIC $(ALERTING) $(LIBPRI_COUNTERS) $(LIBPRI_OPT)
$(STATIC_OBJS)
CFLAGS ?= -g
CFLAGS += -Wall -Werror -Wstrict-prototypes -Wmissing-prototypes
CFLAGS += -fPIC $(ALERTING) $(LIBPRI_OPT) $(COVERAGE_CFLAGS)
INSTALL_PREFIX=$(DESTDIR)
INSTALL_BASE=/usr
libdir?=$(INSTALL_BASE)/lib
SOFLAGS:=-Wl,-h$(DYNAMIC_LIBRARY)
LDCONFIG = /sbin/ldconfig
ifneq ($(findstring Darwin,$(OSARCH)),)
SOFLAGS=$(LDFLAGS) -dynamic -bundle -Xlinker -macosx_version_min -Xlinker 10.4 -Xlinker -undefined -Xlinker dynamic_lookup -force_flat_namespace
ifeq ($(shell /usr/bin/sw_vers -productVersion | cut -c1-4),10.6)
SOFLAGS+=/usr/lib/bundle1.o
endif
LDCONFIG=/usr/bin/true
else
SOFLAGS=$(LDFLAGS) -shared -Wl,-h$(DYNAMIC_LIBRARY) $(COVERAGE_LDFLAGS)
LDCONFIG = /sbin/ldconfig
endif
ifneq (,$(findstring X$(OSARCH)X, XLinuxX XGNU/kFreeBSDX XGNUX))
LDCONFIG_FLAGS=-n
else
@@ -110,11 +93,13 @@ endif
endif
ifeq (${OSARCH},SunOS)
CFLAGS += -DSOLARIS -I../zaptel-solaris
LDCONFIG =
LDCONFIG =
LDCONFIG_FLAGS = \# # Trick to comment out the period in the command below
#INSTALL_PREFIX = /opt/asterisk # Uncomment out to install in standard Solaris location for 3rd party code
endif
UTILITIES= pridump pritest rosetest testprilib
export PRIVERSION
PRIVERSION:=$(shell GREP=$(GREP) AWK=$(AWK) build_tools/make_version .)
@@ -126,7 +111,13 @@ ifeq ($(PROC),sparc64)
PROC=ultrasparc
LIBPRI_OPT = -mtune=$(PROC) -O3 -pipe -fomit-frame-pointer -mcpu=v8
else
LIBPRI_OPT = -O2
ifneq ($(CODE_COVERAGE),)
LIBPRI_OPT=
COVERAGE_CFLAGS=-ftest-coverage -fprofile-arcs
COVERAGE_LDFLAGS=-ftest-coverage -fprofile-arcs
else
LIBPRI_OPT=-O2
endif
endif
ifeq ($(CPUARCH),i686)
@@ -134,7 +125,7 @@ CFLAGS += -m32
SOFLAGS += -m32
endif
all: $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY)
all: $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY) $(UTILITIES)
update:
@if [ -d .svn ]; then \
@@ -160,37 +151,37 @@ ifneq (${OSARCH},SunOS)
install -m 644 libpri.h $(INSTALL_PREFIX)$(INSTALL_BASE)/include
install -m 755 $(DYNAMIC_LIBRARY) $(INSTALL_PREFIX)$(libdir)
#if [ -x /usr/sbin/sestatus ] && ( /usr/sbin/sestatus | grep "SELinux status:" | grep -q "enabled"); then /sbin/restorecon -v $(INSTALL_PREFIX)$(libdir)/$(DYNAMIC_LIBRARY); fi
( cd $(INSTALL_PREFIX)$(libdir) ; ln -sf libpri.so.$(SONAME) libpri.so)
( cd $(INSTALL_PREFIX)$(libdir) ; ln -sf $(DYNAMIC_LIBRARY) libpri.so)
install -m 644 $(STATIC_LIBRARY) $(INSTALL_PREFIX)$(libdir)
if test $$(id -u) = 0; then $(LDCONFIG) $(LDCONFIG_FLAGS) $(INSTALL_PREFIX)$(libdir); fi
else
install -f $(INSTALL_PREFIX)$(INSTALL_BASE)/include -m 644 libpri.h
install -f $(INSTALL_PREFIX)$(libdir) -m 755 $(DYNAMIC_LIBRARY)
( cd $(INSTALL_PREFIX)$(libdir) ; ln -sf libpri.so.$(SONAME) libpri.so)
( cd $(INSTALL_PREFIX)$(libdir) ; ln -sf $(DYNAMIC_LIBRARY) libpri.so)
install -f $(INSTALL_PREFIX)$(libdir) -m 644 $(STATIC_LIBRARY)
endif
uninstall:
@echo "Removing Libpri"
rm -f $(INSTALL_PREFIX)$(libdir)/libpri.so.$(SONAME)
rm -f $(INSTALL_PREFIX)$(libdir)/$(STATIC_LIBRARY)
rm -f $(INSTALL_PREFIX)$(libdir)/libpri.so
rm -f $(INSTALL_PREFIX)$(libdir)/libpri.a
rm -f $(INSTALL_PREFIX)$(libdir)/$(DYNAMIC_LIBRARY)
rm -f $(INSTALL_PREFIX)$(INSTALL_BASE)/include/libpri.h
pritest: pritest.o
$(CC) -o pritest pritest.o -L. -lpri $(CFLAGS)
pritest: pritest.o $(STATIC_LIBRARY)
$(CC) -o $@ $< $(STATIC_LIBRARY) $(CFLAGS)
testprilib.o: testprilib.c
$(CC) $(CFLAGS) -D_REENTRANT -D_GNU_SOURCE -o $@ -c $<
$(CC) $(CFLAGS) -D_REENTRANT -D_GNU_SOURCE $(MAKE_DEPS) -c -o $@ $<
testprilib: testprilib.o
$(CC) -o testprilib testprilib.o -L. -lpri -lpthread $(CFLAGS)
testprilib: testprilib.o $(STATIC_LIBRARY)
$(CC) -o $@ $< $(STATIC_LIBRARY) -lpthread $(CFLAGS)
pridump: pridump.o
$(CC) -o pridump pridump.o -L. -lpri $(CFLAGS)
pridump: pridump.o $(DYNAMIC_LIBRARY)
$(CC) -o $@ $< -L. -lpri $(CFLAGS)
rosetest: rosetest.o
$(CC) -o rosetest rosetest.o -L. -lpri $(CFLAGS)
rosetest: rosetest.o $(STATIC_LIBRARY)
$(CC) -o $@ $< $(STATIC_LIBRARY) $(CFLAGS)
MAKE_DEPS= -MD -MT $@ -MF .$(subst /,_,$@).d -MP
@@ -205,9 +196,9 @@ $(STATIC_LIBRARY): $(STATIC_OBJS)
ranlib $(STATIC_LIBRARY)
$(DYNAMIC_LIBRARY): $(DYNAMIC_OBJS)
$(CC) -shared $(SOFLAGS) -o $@ $(DYNAMIC_OBJS)
$(CC) $(SOFLAGS) -o $@ $(DYNAMIC_OBJS)
$(LDCONFIG) $(LDCONFIG_FLAGS) .
ln -sf libpri.so.$(SONAME) libpri.so
ln -sf $(DYNAMIC_LIBRARY) libpri.so
version.c: FORCE
@build_tools/make_version_c > $@.tmp
@@ -215,9 +206,9 @@ version.c: FORCE
@rm -f $@.tmp
clean:
rm -f *.o *.so *.lo *.so.$(SONAME)
rm -f testprilib $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY)
rm -f pritest pridump
rm -f *.o *.so *.lo
rm -f $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY)
rm -f $(UTILITIES)
rm -f .*.d
.PHONY:

View File

@@ -25,7 +25,13 @@ FSM CC_PTMP_Agent
Action Send_CC_Available(Q931_DISCONNECT);
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_INTERNAL_CLEARING {
Action Release_LinkID;
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Release_LinkID;
Next_State CC_STATE_IDLE;
}
}
@@ -45,22 +51,26 @@ FSM CC_PTMP_Agent
Action Pass_Up_CC_Request;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_INTERNAL_CLEARING {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_TIMEOUT_T_RETENTION {
Action Send_EraseCallLinkageID;
Action Relese_LinkID;
Action Release_LinkID;
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Send_EraseCallLinkageID;
Action Relese_LinkID;
Action Release_LinkID;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_REQUESTED {
Epilog {
Action Send_EraseCallLinkageID;
Action Relese_LinkID;
Action Release_LinkID;
}
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
Next_State CC_STATE_ACTIVATED;

View File

@@ -20,7 +20,14 @@ FSM CC_PTMP_Agent
Action Send_CC_Available(Q931_DISCONNECT);
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_INTERNAL_CLEARING {
Action Release_LinkID;
Action Pass_Up_CC_Cancel;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Release_LinkID;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
@@ -39,9 +46,13 @@ FSM CC_PTMP_Agent
Action Stop_T_RETENTION;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_INTERNAL_CLEARING {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_TIMEOUT_T_RETENTION {
Action Send_EraseCallLinkageID;
Action Relese_LinkID;
Action Release_LinkID;
Action Pass_Up_CC_Cancel;
Action Stop_T_RETENTION;
Action Set_Selfdestruct;
@@ -49,7 +60,7 @@ FSM CC_PTMP_Agent
}
Stimulus CC_EVENT_CANCEL {
Action Send_EraseCallLinkageID;
Action Relese_LinkID;
Action Release_LinkID;
Action Stop_T_RETENTION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
@@ -58,7 +69,7 @@ FSM CC_PTMP_Agent
State CC_STATE_REQUESTED {
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
Action Send_EraseCallLinkageID;
Action Relese_LinkID;
Action Release_LinkID;
/* Start T_CCBS2 or T_CCNR2 depending upon CC mode. */
Action Start_T_SUPERVISION;
Action Reset_A_Status;
@@ -67,7 +78,7 @@ FSM CC_PTMP_Agent
}
Stimulus CC_EVENT_CANCEL {
Action Send_EraseCallLinkageID;
Action Relese_LinkID;
Action Release_LinkID;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}

View File

@@ -25,6 +25,10 @@ FSM CC_PTP_Agent
Action Send_CC_Available(Q931_DISCONNECT);
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_INTERNAL_CLEARING {
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Next_State CC_STATE_IDLE;
}
@@ -53,6 +57,10 @@ FSM CC_PTP_Agent
Action Stop_T_RETENTION;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_INTERNAL_CLEARING {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_TIMEOUT_T_RETENTION {
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;

View File

@@ -20,6 +20,11 @@ FSM CC_PTP_Agent
Action Send_CC_Available(Q931_DISCONNECT);
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_INTERNAL_CLEARING {
Action Pass_Up_CC_Cancel;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
@@ -46,6 +51,10 @@ FSM CC_PTP_Agent
Action Stop_T_RETENTION;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_INTERNAL_CLEARING {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_TIMEOUT_T_RETENTION {
Action Pass_Up_CC_Cancel;
Action Stop_T_RETENTION;

View File

@@ -41,6 +41,10 @@ FSM CC_QSIG_Agent
Action Send_Call_Proceeding;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_INTERNAL_CLEARING {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_TIMEOUT_T_RETENTION {
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;

View File

@@ -34,6 +34,10 @@ FSM CC_QSIG_Agent
Action Stop_T_RETENTION;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_INTERNAL_CLEARING {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_TIMEOUT_T_RETENTION {
Action Pass_Up_CC_Cancel;
Action Stop_T_RETENTION;

View File

@@ -0,0 +1,74 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /><title>Release Summary - libpri-1.4.14</title></head>
<body>
<h1 align="center"><a name="top">Release Summary</a></h1>
<h3 align="center">libpri-1.4.14</h3>
<h3 align="center">Date: 2012-12-20</h3>
<h3 align="center">&lt;asteriskteam@digium.com&gt;</h3>
<hr/>
<h2 align="center">Table of Contents</h2>
<ol>
<li><a href="#summary">Summary</a></li>
<li><a href="#contributors">Contributors</a></li>
<li><a href="#issues">Closed Issues</a></li>
<li><a href="#commits">Other Changes</a></li>
<li><a href="#diffstat">Diffstat</a></li>
</ol>
<hr/>
<a name="summary"><h2 align="center">Summary</h2></a>
<center><a href="#top">[Back to Top]</a></center><br/><p>This release includes only bug fixes. The changes included were made only to address problems that have been identified in this release series. Users should be able to safely upgrade to this version if this release series is already in use. Users considering upgrading from a previous release series are strongly encouraged to review the UPGRADE.txt document as well as the CHANGES document for information about upgrading to this release series.</p>
<p>The data in this summary reflects changes that have been made since the previous release, libpri-1.4.13.</p>
<hr/>
<a name="contributors"><h2 align="center">Contributors</h2></a>
<center><a href="#top">[Back to Top]</a></center><br/><p>This table lists the people who have submitted code, those that have tested patches, as well as those that reported issues on the issue tracker that were resolved in this release. For coders, the number is how many of their patches (of any size) were committed into this release. For testers, the number is the number of times their name was listed as assisting with testing a patch. Finally, for reporters, the number is the number of issues that they reported that were closed by commits that went into this release.</p>
<table width="100%" border="0">
<tr>
<td width="33%"><h3>Coders</h3></td>
<td width="33%"><h3>Testers</h3></td>
<td width="33%"><h3>Reporters</h3></td>
</tr>
<tr valign="top">
<td>
2 rmudgett<br/>
2 Tzafrir Cohen<br/>
</td>
<td>
</td>
<td>
2 tzafrir<br/>
1 nmerrett<br/>
</td>
</tr>
</table>
<hr/>
<a name="issues"><h2 align="center">Closed Issues</h2></a>
<center><a href="#top">[Back to Top]</a></center><br/><p>This is a list of all issues from the issue tracker that were closed by changes that went into this release.</p>
<h3>Category: General</h3><br/>
<a href="https://issues.asterisk.org/jira/browse/PRI-145">PRI-145</a>: Unchecked write in pritest<br/>
Revision: <a href="http://svn.digium.com/view/libpri/branches/1.4?view=revision&revision=2305">2305</a><br/>
Reporter: tzafrir<br/>
Coders: Tzafrir Cohen<br/>
<br/>
<a href="https://issues.asterisk.org/jira/browse/PRI-147">PRI-147</a>: Normal Clearing in Progress Message is ignored<br/>
Revision: <a href="http://svn.digium.com/view/libpri/branches/1.4?view=revision&revision=2308">2308</a><br/>
Reporter: nmerrett<br/>
Coders: rmudgett<br/>
<br/>
<hr/>
<a name="commits"><h2 align="center">Commits Not Associated with an Issue</h2></a>
<center><a href="#top">[Back to Top]</a></center><br/><p>This is a list of all changes that went into this release that did not directly close an issue from the issue tracker. The commits may have been marked as being related to an issue. If that is the case, the issue numbers are listed here, as well.</p>
<table width="100%" border="1">
<tr><td><b>Revision</b></td><td><b>Author</b></td><td><b>Summary</b></td><td><b>Issues Referenced</b></td></tr><tr><td><a href="http://svn.digium.com/view/libpri/branches/1.4?view=revision&revision=2307">2307</a></td><td>rmudgett</td><td>Fix compiler error with ALERTING_NO_PROGRESS define.</td>
<td></td></tr></table>
<hr/>
<a name="diffstat"><h2 align="center">Diffstat Results</h2></a>
<center><a href="#top">[Back to Top]</a></center><br/><p>This is a summary of the changes to the source code that went into this release that was generated using the diffstat utility.</p>
<pre>
pritest.c | 5 +++
q931.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++----------
2 files changed, 71 insertions(+), 13 deletions(-)
</pre><br/>
<hr/>
</body>
</html>

108
libpri-1.4.14-summary.txt Normal file
View File

@@ -0,0 +1,108 @@
Release Summary
libpri-1.4.14
Date: 2012-12-20
<asteriskteam@digium.com>
----------------------------------------------------------------------
Table of Contents
1. Summary
2. Contributors
3. Closed Issues
4. Other Changes
5. Diffstat
----------------------------------------------------------------------
Summary
[Back to Top]
This release includes only bug fixes. The changes included were made only
to address problems that have been identified in this release series.
Users should be able to safely upgrade to this version if this release
series is already in use. Users considering upgrading from a previous
release series are strongly encouraged to review the UPGRADE.txt document
as well as the CHANGES document for information about upgrading to this
release series.
The data in this summary reflects changes that have been made since the
previous release, libpri-1.4.13.
----------------------------------------------------------------------
Contributors
[Back to Top]
This table lists the people who have submitted code, those that have
tested patches, as well as those that reported issues on the issue tracker
that were resolved in this release. For coders, the number is how many of
their patches (of any size) were committed into this release. For testers,
the number is the number of times their name was listed as assisting with
testing a patch. Finally, for reporters, the number is the number of
issues that they reported that were closed by commits that went into this
release.
Coders Testers Reporters
2 rmudgett 2 tzafrir
2 Tzafrir Cohen 1 nmerrett
----------------------------------------------------------------------
Closed Issues
[Back to Top]
This is a list of all issues from the issue tracker that were closed by
changes that went into this release.
Category: General
PRI-145: Unchecked write in pritest
Revision: 2305
Reporter: tzafrir
Coders: Tzafrir Cohen
PRI-147: Normal Clearing in Progress Message is ignored
Revision: 2308
Reporter: nmerrett
Coders: rmudgett
----------------------------------------------------------------------
Commits Not Associated with an Issue
[Back to Top]
This is a list of all changes that went into this release that did not
directly close an issue from the issue tracker. The commits may have been
marked as being related to an issue. If that is the case, the issue
numbers are listed here, as well.
+------------------------------------------------------------------------+
| Revision | Author | Summary | Issues |
| | | | Referenced |
|----------+----------+-------------------------------------+------------|
| 2307 | rmudgett | Fix compiler error with | |
| | | ALERTING_NO_PROGRESS define. | |
+------------------------------------------------------------------------+
----------------------------------------------------------------------
Diffstat Results
[Back to Top]
This is a summary of the changes to the source code that went into this
release that was generated using the diffstat utility.
pritest.c | 5 +++
q931.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++----------
2 files changed, 71 insertions(+), 13 deletions(-)
----------------------------------------------------------------------

158
libpri.h
View File

@@ -547,6 +547,7 @@ struct pri_rerouting_data {
#define PRI_SUBCMD_AOC_CHARGING_REQ_RSP 22 /*!< Advice Of Charge Request Response information */
#define PRI_SUBCMD_MCID_REQ 23 /*!< Malicious Call ID Request */
#define PRI_SUBCMD_MCID_RSP 24 /*!< Malicious Call ID Request response */
#define PRI_SUBCMD_DISPLAY_TEXT 25 /*!< Received display ie text */
#if defined(STATUS_REQUEST_PLACE_HOLDER)
struct pri_subcmd_status_request {
@@ -967,6 +968,35 @@ struct pri_subcmd_mcid_rsp {
int fail_code;
};
struct pri_subcmd_display_txt {
/*!
* \brief Character set the text is using.
* \details
* unknown(0),
* iso8859-1(1),
* enum-value-withdrawn-by-ITU-T(2)
* iso8859-2(3),
* iso8859-3(4),
* iso8859-4(5),
* iso8859-5(6),
* iso8859-7(7),
* iso10646-BmpString(8),
* iso10646-utf-8String(9)
*/
int char_set;
/*!
* \brief Number of octets in the display message.
* \note Not including any added null terminator.
*/
int length;
/*!
* \brief Display text data.
* \note Null terminated on receive.
* \note Does not need to be null terminated on send.
*/
char text[128];
};
struct pri_subcommand {
/*! PRI_SUBCMD_xxx defined values */
int cmd;
@@ -999,6 +1029,7 @@ struct pri_subcommand {
struct pri_subcmd_aoc_e aoc_e;
struct pri_subcmd_mcid_req mcid_req;
struct pri_subcmd_mcid_rsp mcid_rsp;
struct pri_subcmd_display_txt display;
} u;
};
@@ -1590,11 +1621,11 @@ int pri_mwi_deactivate(struct pri *pri, q931_call *c, char *caller, int callerpl
* \brief Send a MWI indication on the specified D channel.
*
* \param ctrl D channel controller.
* \param mailbox Controlling party number (NULL if not present).
* \param mailbox Party receiving notification.
* \param basic_service Basic service enum (-1 if not present).
* \param num_messages NumberOfMessages (-1 if not present).
* \param caller_id Controlling party privided number (NULL if not present).
* \param timestamp Generalized Time format (NULL if not present).
* \param caller_id Party leaving message (NULL if not present).
* \param timestamp When message left. (Generalized Time format, NULL if not present)
* \param message_reference Message reference number (-1 if not present).
* \param message_status Message status: added(0), removed(1).
*
@@ -1605,6 +1636,27 @@ int pri_mwi_indicate(struct pri *ctrl, const struct pri_party_id *mailbox,
int basic_service, int num_messages, const struct pri_party_id *caller_id,
const char *timestamp, int message_reference, int message_status);
/*!
* \brief Send a MWI indication on the specified D channel. (Take two)
*
* \param ctrl D channel controller.
* \param mailbox Party receiving notification.
* \param vm_id Voicemail system number (NULL if not present).
* \param basic_service Basic service enum (-1 if not present).
* \param num_messages NumberOfMessages (-1 if not present).
* \param caller_id Party leaving message (NULL if not present).
* \param timestamp When message left. (Generalized Time format, NULL if not present)
* \param message_reference Message reference number (-1 if not present).
* \param message_status Message status: added(0), removed(1).
*
* \retval 0 on success.
* \retval -1 on error.
*/
int pri_mwi_indicate_v2(struct pri *ctrl, const struct pri_party_id *mailbox,
const struct pri_party_id *vm_id, int basic_service, int num_messages,
const struct pri_party_id *caller_id, const char *timestamp, int message_reference,
int message_status);
/* Set service message support flag */
int pri_set_service_message_support(struct pri *pri, int supportflag);
@@ -1840,6 +1892,80 @@ int pri_transfer_rsp(struct pri *ctrl, q931_call *call, int invoke_id, int is_su
*/
void pri_aoc_events_enable(struct pri *ctrl, int enable);
enum pri_layer2_persistence {
PRI_L2_PERSISTENCE_DEFAULT,
/*! Immediately bring layer 2 back up if the peer brings layer 2 down. */
PRI_L2_PERSISTENCE_KEEP_UP,
/*! Leave layer 2 down if the peer brings layer 2 down. */
PRI_L2_PERSISTENCE_LEAVE_DOWN,
#if 0 /* Possible future option. Would need to define how long to idle before dropping. */
/*! Drop layer 2 on D channel idle. */
PRI_L2_PERSISTENCE_IDLE_DROP,
#endif
};
/*!
* \brief Set the layer2 persistence option.
*
* \param ctrl D channel controller.
* \param option Layer 2 persistence to apply.
*
* \note
* Not all values are supported by all modes.
*
* \return Nothing
*/
void pri_persistent_layer2_option(struct pri *ctrl, enum pri_layer2_persistence option);
#define PRI_DISPLAY_OPTION_BLOCK (1 << 0) /*!< Do not pass display text. */
#define PRI_DISPLAY_OPTION_NAME_INITIAL (1 << 1) /*!< Use display in SETUP/CONNECT for name. */
#define PRI_DISPLAY_OPTION_NAME_UPDATE (1 << 2) /*!< Use display in FACILITY/NOTIFY for COLP name if appropriate. */
#define PRI_DISPLAY_OPTION_TEXT (1 << 3) /*!< Pass arbitrary display text in INFORMATION messages during call. */
/*!
* \brief Set the display ie send policy options.
*
* \param ctrl D channel controller.
* \param flags Option flags to apply.
*
* \note
* If no flags set then legacy default behaviour.
*
* \note
* Not all options are supported by all switches.
*
* \return Nothing
*/
void pri_display_options_send(struct pri *ctrl, unsigned long flags);
/*!
* \brief Set the display ie receive policy options.
*
* \param ctrl D channel controller.
* \param flags Option flags to apply.
*
* \note
* If no flags set then legacy default behaviour.
*
* \note
* Not all options are supported by all switches.
*
* \return Nothing
*/
void pri_display_options_receive(struct pri *ctrl, unsigned long flags);
/*!
* \brief Send display text during a call.
*
* \param ctrl D channel controller.
* \param call Q.931 call leg
* \param display Display text to send.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int pri_display_text(struct pri *ctrl, q931_call *call, const struct pri_subcmd_display_txt *display);
/*!
* \brief Set the call hold feature enable flag.
*
@@ -2001,6 +2127,27 @@ void pri_cc_status(struct pri *ctrl, long cc_id, int status);
int pri_cc_call(struct pri *ctrl, long cc_id, q931_call *call, struct pri_sr *req);
void pri_cc_cancel(struct pri *ctrl, long cc_id);
/* Date/time ie send policy option values. */
#define PRI_DATE_TIME_SEND_DEFAULT 0 /*!< Send date/time ie default. */
#define PRI_DATE_TIME_SEND_NO 1 /*!< Send date/time ie never. */
#define PRI_DATE_TIME_SEND_DATE 2 /*!< Send date/time ie date only. */
#define PRI_DATE_TIME_SEND_DATE_HH 3 /*!< Send date/time ie date and hour. */
#define PRI_DATE_TIME_SEND_DATE_HHMM 4 /*!< Send date/time ie date, hour, and minute. */
#define PRI_DATE_TIME_SEND_DATE_HHMMSS 5 /*!< Send date/time ie date, hour, minute, and second. */
/*!
* \brief Set the date/time ie send policy option.
*
* \param ctrl D channel controller.
* \param option Policy option to set.
*
* \note
* Only valid in NT mode.
*
* \return Nothing
*/
void pri_date_time_send_option(struct pri *ctrl, int option);
/* Get/Set PRI Timers */
#define PRI_GETSET_TIMERS
int pri_set_timer(struct pri *pri, int timer, int value);
@@ -2032,7 +2179,7 @@ enum PRI_TIMERS_AND_COUNTERS {
PRI_TIMER_T310, /*!< Maximum time between receiving a CALL_PROCEEDING and receiving a ALERT/CONNECT/DISCONNECT/PROGRESS */
PRI_TIMER_T313, /*!< Wait for CONNECT acknowledge, CPE side only */
PRI_TIMER_T314,
PRI_TIMER_T316, /*!< Maximum time between transmitting a RESTART and receiving a RESTART ACK */
PRI_TIMER_T316, /*!< Time to wait for a RESTART ACK before retransmitting RESTART. (Timer enabled if greater than zero.) */
PRI_TIMER_T317,
PRI_TIMER_T318,
PRI_TIMER_T319,
@@ -2073,6 +2220,9 @@ enum PRI_TIMERS_AND_COUNTERS {
PRI_TIMER_QSIG_CC_T3, /*!< Max time to wait for user A to respond to user B availability. */
PRI_TIMER_QSIG_CC_T4, /*!< Path reservation supervision timeout. */
PRI_TIMER_T312, /*!< Supervise broadcast SETUP message call reference retention. */
PRI_TIMER_N316, /*!< Number of times to transmit RESTART before giving up if T316 enabled. */
/* Must be last in the enum list */
PRI_MAX_TIMERS
};

925
pri.c

File diff suppressed because it is too large Load Diff

View File

@@ -212,7 +212,7 @@ void aoc_etsi_aoc_request(struct pri *ctrl, q931_call *call, const struct rose_m
struct pri_subcommand *subcmd;
int request;
if (!PRI_MASTER(ctrl)->aoc_support) {
if (!ctrl->aoc_support) {
send_facility_error(ctrl, call, invoke->invoke_id, ROSE_ERROR_Gen_NotSubscribed);
return;
}
@@ -439,7 +439,7 @@ void aoc_etsi_aoc_s_currency(struct pri *ctrl, const struct rose_msg_invoke *inv
{
struct pri_subcommand *subcmd;
if (!PRI_MASTER(ctrl)->aoc_support) {
if (!ctrl->aoc_support) {
return;
}
subcmd = q931_alloc_subcommand(ctrl);
@@ -470,7 +470,7 @@ void aoc_etsi_aoc_s_special_arrangement(struct pri *ctrl, const struct rose_msg_
{
struct pri_subcommand *subcmd;
if (!PRI_MASTER(ctrl)->aoc_support) {
if (!ctrl->aoc_support) {
return;
}
subcmd = q931_alloc_subcommand(ctrl);
@@ -535,7 +535,7 @@ void aoc_etsi_aoc_d_currency(struct pri *ctrl, const struct rose_msg_invoke *inv
{
struct pri_subcommand *subcmd;
if (!PRI_MASTER(ctrl)->aoc_support) {
if (!ctrl->aoc_support) {
return;
}
subcmd = q931_alloc_subcommand(ctrl);
@@ -577,7 +577,7 @@ void aoc_etsi_aoc_d_charging_unit(struct pri *ctrl, const struct rose_msg_invoke
{
struct pri_subcommand *subcmd;
if (!PRI_MASTER(ctrl)->aoc_support) {
if (!ctrl->aoc_support) {
return;
}
subcmd = q931_alloc_subcommand(ctrl);
@@ -760,7 +760,7 @@ void aoc_etsi_aoc_e_currency(struct pri *ctrl, q931_call *call, const struct ros
{
struct pri_subcommand *subcmd;
if (!PRI_MASTER(ctrl)->aoc_support) {
if (!ctrl->aoc_support) {
return;
}
subcmd = q931_alloc_subcommand(ctrl);
@@ -828,7 +828,7 @@ void aoc_etsi_aoc_e_charging_unit(struct pri *ctrl, q931_call *call, const struc
}
}
if (!PRI_MASTER(ctrl)->aoc_support) {
if (!ctrl->aoc_support) {
return;
}
subcmd = q931_alloc_subcommand(ctrl);
@@ -869,7 +869,6 @@ void aoc_etsi_aoc_e_charging_unit(struct pri *ctrl, q931_call *call, const struc
void pri_aoc_events_enable(struct pri *ctrl, int enable)
{
if (ctrl) {
ctrl = PRI_MASTER(ctrl);
ctrl->aoc_support = enable ? 1 : 0;
}
}
@@ -1610,7 +1609,7 @@ static int aoc_e_encode(struct pri *ctrl, q931_call *call, const struct pri_subc
int pri_aoc_de_request_response_send(struct pri *ctrl, q931_call *call, int response, int invoke_id)
{
if (!ctrl || !call) {
if (!ctrl || !pri_is_call_valid(ctrl, call)) {
return -1;
}
@@ -1629,7 +1628,7 @@ int pri_aoc_de_request_response_send(struct pri *ctrl, q931_call *call, int resp
int pri_aoc_s_request_response_send(struct pri *ctrl, q931_call *call, int invoke_id, const struct pri_subcmd_aoc_s *aoc_s)
{
if (!ctrl || !call) {
if (!ctrl || !pri_is_call_valid(ctrl, call)) {
return -1;
}
@@ -1692,7 +1691,7 @@ int aoc_charging_request_send(struct pri *ctrl, q931_call *call, enum PRI_AOC_RE
int pri_aoc_s_send(struct pri *ctrl, q931_call *call, const struct pri_subcmd_aoc_s *aoc_s)
{
if (!ctrl || !call) {
if (!ctrl || !pri_is_call_valid(ctrl, call)) {
return -1;
}
@@ -1711,7 +1710,7 @@ int pri_aoc_s_send(struct pri *ctrl, q931_call *call, const struct pri_subcmd_ao
int pri_aoc_d_send(struct pri *ctrl, q931_call *call, const struct pri_subcmd_aoc_d *aoc_d)
{
if (!ctrl || !call) {
if (!ctrl || !pri_is_call_valid(ctrl, call)) {
return -1;
}
@@ -1729,7 +1728,7 @@ int pri_aoc_d_send(struct pri *ctrl, q931_call *call, const struct pri_subcmd_ao
int pri_aoc_e_send(struct pri *ctrl, q931_call *call, const struct pri_subcmd_aoc_e *aoc_e)
{
if (!ctrl || !call) {
if (!ctrl || !pri_is_call_valid(ctrl, call)) {
return -1;
}

View File

@@ -61,7 +61,6 @@ struct pri_cc_record *pri_cc_find_by_reference(struct pri *ctrl, unsigned refere
{
struct pri_cc_record *cc_record;
ctrl = PRI_MASTER(ctrl);
for (cc_record = ctrl->cc.pool; cc_record; cc_record = cc_record->next) {
if (cc_record->ccbs_reference_id == reference_id) {
/* Found the record */
@@ -85,7 +84,6 @@ struct pri_cc_record *pri_cc_find_by_linkage(struct pri *ctrl, unsigned linkage_
{
struct pri_cc_record *cc_record;
ctrl = PRI_MASTER(ctrl);
for (cc_record = ctrl->cc.pool; cc_record; cc_record = cc_record->next) {
if (cc_record->call_linkage_id == linkage_id) {
/* Found the record */
@@ -110,7 +108,6 @@ static struct pri_cc_record *pri_cc_find_by_id(struct pri *ctrl, long cc_id)
{
struct pri_cc_record *cc_record;
ctrl = PRI_MASTER(ctrl);
for (cc_record = ctrl->cc.pool; cc_record; cc_record = cc_record->next) {
if (cc_record->record_id == cc_id) {
/* Found the record */
@@ -234,7 +231,6 @@ struct pri_cc_record *pri_cc_find_by_addressing(struct pri *ctrl, const struct q
struct q931_party_address addr_a;
struct q931_party_address addr_b;
ctrl = PRI_MASTER(ctrl);
addr_a = *party_a;
addr_b = *party_b;
for (cc_record = ctrl->cc.pool; cc_record; cc_record = cc_record->next) {
@@ -266,7 +262,6 @@ static int pri_cc_new_reference_id(struct pri *ctrl)
long reference_id;
long first_id;
ctrl = PRI_MASTER(ctrl);
ctrl->cc.last_reference_id = (ctrl->cc.last_reference_id + 1) & 0x7F;
reference_id = ctrl->cc.last_reference_id;
first_id = reference_id;
@@ -298,7 +293,6 @@ static int pri_cc_new_linkage_id(struct pri *ctrl)
long linkage_id;
long first_id;
ctrl = PRI_MASTER(ctrl);
ctrl->cc.last_linkage_id = (ctrl->cc.last_linkage_id + 1) & 0x7F;
linkage_id = ctrl->cc.last_linkage_id;
first_id = linkage_id;
@@ -330,7 +324,6 @@ static long pri_cc_new_id(struct pri *ctrl)
long record_id;
long first_id;
ctrl = PRI_MASTER(ctrl);
record_id = ++ctrl->cc.last_record_id;
first_id = record_id;
while (pri_cc_find_by_id(ctrl, record_id)) {
@@ -386,7 +379,6 @@ static void pri_cc_delete_record(struct pri *ctrl, struct pri_cc_record *doomed)
}
pri_cc_disassociate_signaling_link(doomed);
ctrl = PRI_MASTER(ctrl);
for (prev = &ctrl->cc.pool, current = ctrl->cc.pool; current;
prev = &current->next, current = current->next) {
if (current == doomed) {
@@ -413,7 +405,6 @@ struct pri_cc_record *pri_cc_new_record(struct pri *ctrl, q931_call *call)
struct pri_cc_record *cc_record;
long record_id;
ctrl = PRI_MASTER(ctrl);
record_id = pri_cc_new_id(ctrl);
if (record_id < 0) {
return NULL;
@@ -424,7 +415,7 @@ struct pri_cc_record *pri_cc_new_record(struct pri *ctrl, q931_call *call)
}
/* Initialize the new record */
cc_record->master = ctrl;
cc_record->ctrl = ctrl;
cc_record->record_id = record_id;
cc_record->call_linkage_id = CC_PTMP_INVALID_ID;/* So it will never be found this way */
cc_record->ccbs_reference_id = CC_PTMP_INVALID_ID;/* So it will never be found this way */
@@ -975,7 +966,7 @@ static unsigned char *enc_qsig_cc_request(struct pri *ctrl,
//msg.args.qsig.CcbsRequest.can_retain_service = 0;
switch (PRI_MASTER(ctrl)->cc.option.signaling_retention_req) {
switch (ctrl->cc.option.signaling_retention_req) {
case 0:/* Want release signaling link. */
cc_record->option.retain_signaling_link = 0;
@@ -1954,7 +1945,6 @@ static unsigned char *enc_etsi_ptmp_cc_interrogate_rsp_general(struct pri *ctrl,
struct q931_party_number party_a_number;
const struct pri_cc_record *cc_record;
unsigned char *new_pos;
struct pri *master;
unsigned idx;
pos = facility_encode_header(ctrl, pos, end, NULL);
@@ -1966,8 +1956,7 @@ static unsigned char *enc_etsi_ptmp_cc_interrogate_rsp_general(struct pri *ctrl,
msg.invoke_id = invoke->invoke_id;
msg.operation = invoke->operation;
master = PRI_MASTER(ctrl);
msg.args.etsi.CCBSInterrogate.recall_mode = master->cc.option.recall_mode;
msg.args.etsi.CCBSInterrogate.recall_mode = ctrl->cc.option.recall_mode;
/* Convert the given party A number. */
q931_party_number_init(&party_a_number);
@@ -1979,7 +1968,7 @@ static unsigned char *enc_etsi_ptmp_cc_interrogate_rsp_general(struct pri *ctrl,
/* Build the CallDetails list. */
idx = 0;
for (cc_record = master->cc.pool; cc_record; cc_record = cc_record->next) {
for (cc_record = ctrl->cc.pool; cc_record; cc_record = cc_record->next) {
if (cc_record->ccbs_reference_id == CC_PTMP_INVALID_ID
|| (!cc_record->is_ccnr) != (invoke->operation == ROSE_ETSI_CCBSInterrogate)) {
/*
@@ -2087,7 +2076,7 @@ int pri_cc_interrogate_rsp(struct pri *ctrl, q931_call *call, const struct rose_
{
int encode_result;
if (!PRI_MASTER(ctrl)->cc_support) {
if (!ctrl->cc_support) {
/* Call completion is disabled. */
return send_facility_error(ctrl, call, invoke->invoke_id,
ROSE_ERROR_Gen_NotSubscribed);
@@ -2134,7 +2123,7 @@ void pri_cc_ptmp_request(struct pri *ctrl, q931_call *call, const struct rose_ms
{
struct pri_cc_record *cc_record;
if (!PRI_MASTER(ctrl)->cc_support) {
if (!ctrl->cc_support) {
/* Call completion is disabled. */
send_facility_error(ctrl, call, invoke->invoke_id,
ROSE_ERROR_Gen_NotSubscribed);
@@ -2191,7 +2180,7 @@ void pri_cc_ptp_request(struct pri *ctrl, q931_call *call, int msgtype, const st
/* Ignore CC request message since it did not come in on the correct message. */
return;
}
if (!PRI_MASTER(ctrl)->cc_support) {
if (!ctrl->cc_support) {
/* Call completion is disabled. */
rose_error_msg_encode(ctrl, call, Q931_ANY_MESSAGE, invoke->invoke_id,
ROSE_ERROR_Gen_NotSubscribed);
@@ -2230,8 +2219,7 @@ void pri_cc_ptp_request(struct pri *ctrl, q931_call *call, int msgtype, const st
party_a.number.presentation =
PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
} else {
party_a.number.presentation =
PRI_PRES_UNAVAILABLE | PRI_PRES_USER_NUMBER_UNSCREENED;
party_a.number.presentation = PRES_NUMBER_NOT_AVAILABLE;
}
} else {
party_a.number.presentation =
@@ -2270,7 +2258,6 @@ void pri_cc_ptp_request(struct pri *ctrl, q931_call *call, int msgtype, const st
*/
void pri_cc_qsig_request(struct pri *ctrl, q931_call *call, int msgtype, const struct rose_msg_invoke *invoke)
{
struct pri *master;
struct pri_cc_record *cc_record;
struct q931_party_address party_a;
struct q931_party_address party_b;
@@ -2279,8 +2266,7 @@ void pri_cc_qsig_request(struct pri *ctrl, q931_call *call, int msgtype, const s
/* Ignore CC request message since it did not come in on the correct message. */
return;
}
master = PRI_MASTER(ctrl);
if (!master->cc_support) {
if (!ctrl->cc_support) {
/* Call completion is disabled. */
rose_error_msg_encode(ctrl, call, Q931_ANY_MESSAGE, invoke->invoke_id,
ROSE_ERROR_QSIG_LongTermRejection);
@@ -2302,7 +2288,7 @@ void pri_cc_qsig_request(struct pri *ctrl, q931_call *call, int msgtype, const s
rose_copy_subaddress_to_q931(ctrl, &party_b.subaddress,
&invoke->args.qsig.CcbsRequest.subaddr_b);
cc_record = pri_cc_find_by_addressing(master, &party_a, &party_b,
cc_record = pri_cc_find_by_addressing(ctrl, &party_a, &party_b,
invoke->args.qsig.CcbsRequest.q931ie.length,
invoke->args.qsig.CcbsRequest.q931ie.contents);
if (!cc_record || cc_record->state != CC_STATE_AVAILABLE) {
@@ -2321,7 +2307,7 @@ void pri_cc_qsig_request(struct pri *ctrl, q931_call *call, int msgtype, const s
} else {
/* The originator does not care. Do how we are configured. */
cc_record->option.retain_signaling_link =
master->cc.option.signaling_retention_rsp;
ctrl->cc.option.signaling_retention_rsp;
}
if (!cc_record->party_a.number.valid || cc_record->party_a.number.str[0] == '\0') {
/*
@@ -2517,14 +2503,13 @@ void pri_cc_qsig_exec_possible(struct pri *ctrl, q931_call *call, int msgtype, c
}
/*!
* \internal
* \brief Convert the given call completion state to a string.
*
* \param state CC state to convert to string.
*
* \return String version of call completion state.
*/
static const char *pri_cc_fsm_state_str(enum CC_STATES state)
const char *pri_cc_fsm_state_str(enum CC_STATES state)
{
const char *str;
@@ -2568,14 +2553,13 @@ static const char *pri_cc_fsm_state_str(enum CC_STATES state)
}
/*!
* \internal
* \brief Convert the given call completion event to a string.
*
* \param event CC event to convert to string.
*
* \return String version of call completion event.
*/
static const char *pri_cc_fsm_event_str(enum CC_EVENTS event)
const char *pri_cc_fsm_event_str(enum CC_EVENTS event)
{
const char *str;
@@ -2626,6 +2610,9 @@ static const char *pri_cc_fsm_event_str(enum CC_EVENTS event)
case CC_EVENT_CANCEL:
str = "CC_EVENT_CANCEL";
break;
case CC_EVENT_INTERNAL_CLEARING:
str = "CC_EVENT_INTERNAL_CLEARING";
break;
case CC_EVENT_SIGNALING_GONE:
str = "CC_EVENT_SIGNALING_GONE";
break;
@@ -2805,7 +2792,7 @@ static void pri_cc_timeout_t_retention(void *data)
struct pri_cc_record *cc_record = data;
cc_record->t_retention = 0;
q931_cc_timeout(cc_record->master, cc_record, CC_EVENT_TIMEOUT_T_RETENTION);
q931_cc_timeout(cc_record->ctrl, cc_record, CC_EVENT_TIMEOUT_T_RETENTION);
}
/*!
@@ -2857,7 +2844,7 @@ static void pri_cc_timeout_extended_t_ccbs1(void *data)
struct pri_cc_record *cc_record = data;
cc_record->fsm.ptmp.extended_t_ccbs1 = 0;
q931_cc_timeout(cc_record->master, cc_record, CC_EVENT_TIMEOUT_EXTENDED_T_CCBS1);
q931_cc_timeout(cc_record->ctrl, cc_record, CC_EVENT_TIMEOUT_EXTENDED_T_CCBS1);
}
/*!
@@ -2911,7 +2898,7 @@ static void pri_cc_timeout_t_supervision(void *data)
struct pri_cc_record *cc_record = data;
cc_record->t_supervision = 0;
q931_cc_timeout(cc_record->master, cc_record, CC_EVENT_TIMEOUT_T_SUPERVISION);
q931_cc_timeout(cc_record->ctrl, cc_record, CC_EVENT_TIMEOUT_T_SUPERVISION);
}
/*!
@@ -2991,7 +2978,7 @@ static void pri_cc_timeout_t_recall(void *data)
struct pri_cc_record *cc_record = data;
cc_record->t_recall = 0;
q931_cc_timeout(cc_record->master, cc_record, CC_EVENT_TIMEOUT_T_RECALL);
q931_cc_timeout(cc_record->ctrl, cc_record, CC_EVENT_TIMEOUT_T_RECALL);
}
/*!
@@ -3755,7 +3742,7 @@ static void pri_cc_indirect_status_rsp_a(void *data)
struct pri_cc_record *cc_record = data;
cc_record->t_indirect = 0;
q931_cc_indirect(cc_record->master, cc_record, pri_cc_fill_status_rsp_a);
q931_cc_indirect(cc_record->ctrl, cc_record, pri_cc_fill_status_rsp_a);
}
/*!
@@ -3904,7 +3891,7 @@ static void pri_cc_indirect_status_a(void *data)
struct pri_cc_record *cc_record = data;
cc_record->t_indirect = 0;
q931_cc_indirect(cc_record->master, cc_record, pri_cc_fill_status_a);
q931_cc_indirect(cc_record->ctrl, cc_record, pri_cc_fill_status_a);
}
/*!
@@ -4261,7 +4248,7 @@ static void pri_cc_post_hangup_signaling(void *data)
struct pri_cc_record *cc_record = data;
cc_record->t_indirect = 0;
q931_cc_timeout(cc_record->master, cc_record, CC_EVENT_HANGUP_SIGNALING);
q931_cc_timeout(cc_record->ctrl, cc_record, CC_EVENT_HANGUP_SIGNALING);
}
/*!
@@ -4364,7 +4351,14 @@ static void pri_cc_fsm_ptmp_agent_pend_avail(struct pri *ctrl, q931_call *call,
pri_cc_act_send_cc_available(ctrl, cc_record, call, Q931_DISCONNECT);
cc_record->state = CC_STATE_AVAILABLE;
break;
case CC_EVENT_INTERNAL_CLEARING:
pri_cc_act_release_link_id(ctrl, cc_record);
pri_cc_act_pass_up_cc_cancel(ctrl, cc_record);
pri_cc_act_set_self_destruct(ctrl, cc_record);
cc_record->state = CC_STATE_IDLE;
break;
case CC_EVENT_CANCEL:
pri_cc_act_release_link_id(ctrl, cc_record);
pri_cc_act_set_self_destruct(ctrl, cc_record);
cc_record->state = CC_STATE_IDLE;
break;
@@ -4397,6 +4391,10 @@ static void pri_cc_fsm_ptmp_agent_avail(struct pri *ctrl, q931_call *call, struc
pri_cc_act_stop_t_retention(ctrl, cc_record);
cc_record->state = CC_STATE_REQUESTED;
break;
case CC_EVENT_INTERNAL_CLEARING:
pri_cc_act_stop_t_retention(ctrl, cc_record);
pri_cc_act_start_t_retention(ctrl, cc_record);
break;
case CC_EVENT_TIMEOUT_T_RETENTION:
pri_cc_act_send_erase_call_linkage_id(ctrl, cc_record);
pri_cc_act_release_link_id(ctrl, cc_record);
@@ -5288,6 +5286,11 @@ static void pri_cc_fsm_ptp_agent_pend_avail(struct pri *ctrl, q931_call *call, s
pri_cc_act_send_cc_available(ctrl, cc_record, call, Q931_DISCONNECT);
cc_record->state = CC_STATE_AVAILABLE;
break;
case CC_EVENT_INTERNAL_CLEARING:
pri_cc_act_pass_up_cc_cancel(ctrl, cc_record);
pri_cc_act_set_self_destruct(ctrl, cc_record);
cc_record->state = CC_STATE_IDLE;
break;
case CC_EVENT_CANCEL:
pri_cc_act_set_self_destruct(ctrl, cc_record);
cc_record->state = CC_STATE_IDLE;
@@ -5328,6 +5331,10 @@ static void pri_cc_fsm_ptp_agent_avail(struct pri *ctrl, q931_call *call, struct
pri_cc_act_stop_t_retention(ctrl, cc_record);
cc_record->state = CC_STATE_REQUESTED;
break;
case CC_EVENT_INTERNAL_CLEARING:
pri_cc_act_stop_t_retention(ctrl, cc_record);
pri_cc_act_start_t_retention(ctrl, cc_record);
break;
case CC_EVENT_TIMEOUT_T_RETENTION:
pri_cc_act_pass_up_cc_cancel(ctrl, cc_record);
pri_cc_act_stop_t_retention(ctrl, cc_record);
@@ -5927,6 +5934,10 @@ static void pri_cc_fsm_qsig_agent_avail(struct pri *ctrl, q931_call *call, struc
pri_cc_act_stop_t_retention(ctrl, cc_record);
cc_record->state = CC_STATE_REQUESTED;
break;
case CC_EVENT_INTERNAL_CLEARING:
pri_cc_act_stop_t_retention(ctrl, cc_record);
pri_cc_act_start_t_retention(ctrl, cc_record);
break;
case CC_EVENT_TIMEOUT_T_RETENTION:
pri_cc_act_pass_up_cc_cancel(ctrl, cc_record);
pri_cc_act_stop_t_retention(ctrl, cc_record);
@@ -6803,7 +6814,7 @@ long pri_cc_available(struct pri *ctrl, q931_call *call)
struct pri_cc_record *cc_record;
long cc_id;
if (!ctrl || !call) {
if (!ctrl || !pri_is_call_valid(ctrl, call)) {
return -1;
}
if (call->cc.record) {
@@ -6850,7 +6861,7 @@ long pri_cc_available(struct pri *ctrl, q931_call *call)
break;
}
cc_record->call_linkage_id = linkage_id;
cc_record->signaling = PRI_MASTER(ctrl)->dummy_call;
cc_record->signaling = ctrl->link.dummy_call;
} else {
cc_record = pri_cc_new_record(ctrl, call);
if (!cc_record) {
@@ -6894,7 +6905,7 @@ void pri_cc_qsig_determine_available(struct pri *ctrl, q931_call *call)
return;
}
if (!PRI_MASTER(ctrl)->cc_support) {
if (!ctrl->cc_support) {
/*
* Blocking the cc-available event effectively
* disables call completion for outgoing calls.
@@ -7811,7 +7822,7 @@ int pri_cc_call(struct pri *ctrl, long cc_id, q931_call *call, struct pri_sr *re
{
struct pri_cc_record *cc_record;
if (!ctrl || !call || !req) {
if (!ctrl || !pri_is_call_valid(ctrl, call) || !req) {
return -1;
}
cc_record = pri_cc_find_by_id(ctrl, cc_id);

View File

@@ -632,6 +632,9 @@ void rose_copy_presented_number_screened_to_q931(struct pri *ctrl,
rose_copy_number_to_q931(ctrl, q931_number,
&rose_presented->screened.number);
break;
case 2: /* numberNotAvailableDueToInterworking */
q931_number->presentation = PRES_NUMBER_NOT_AVAILABLE;
break;
default:
q931_number->presentation |= PRI_PRES_USER_NUMBER_UNSCREENED;
break;
@@ -660,6 +663,9 @@ void rose_copy_presented_number_unscreened_to_q931(struct pri *ctrl,
case 3: /* presentationRestrictedNumber */
rose_copy_number_to_q931(ctrl, q931_number, &rose_presented->number);
break;
case 2: /* numberNotAvailableDueToInterworking */
q931_number->presentation = PRES_NUMBER_NOT_AVAILABLE;
break;
default:
break;
}
@@ -693,6 +699,9 @@ void rose_copy_presented_address_screened_to_id_q931(struct pri *ctrl,
rose_copy_subaddress_to_q931(ctrl, &q931_address->subaddress,
&rose_presented->screened.subaddress);
break;
case 2: /* numberNotAvailableDueToInterworking */
q931_address->number.presentation = PRES_NUMBER_NOT_AVAILABLE;
break;
default:
q931_address->number.presentation |= PRI_PRES_USER_NUMBER_UNSCREENED;
break;
@@ -1746,11 +1755,11 @@ int mwi_message_send(struct pri *ctrl, q931_call *call, struct pri_sr *req, int
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode the facility ie contents.
* \param end End of facility ie contents encoding data buffer.
* \param mailbox Controlling party number (NULL if not present).
* \param vm_id Controlling party number (NULL if not present).
* \param basic_service Basic service enum (-1 if not present).
* \param num_messages NumberOfMessages (-1 if not present).
* \param caller_id Controlling party privided number (NULL if not present).
* \param timestamp Generalized Time format (NULL if not present).
* \param timestamp When message left. (Generalized Time format, NULL if not present)
* \param message_reference Message reference number (-1 if not present).
* \param message_status Message status: added(0), removed(1).
*
@@ -1758,7 +1767,7 @@ int mwi_message_send(struct pri *ctrl, q931_call *call, struct pri_sr *req, int
* \retval NULL on error.
*/
static unsigned char *enc_etsi_mwi_indicate_message(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const struct pri_party_id *mailbox, int basic_service,
unsigned char *end, const struct pri_party_id *vm_id, int basic_service,
int num_messages, const struct pri_party_id *caller_id, const char *timestamp,
int message_reference, int message_status)
{
@@ -1774,8 +1783,8 @@ static unsigned char *enc_etsi_mwi_indicate_message(struct pri *ctrl, unsigned c
msg.operation = ROSE_ETSI_MWIIndicate;
msg.invoke_id = get_invokeid(ctrl);
if (mailbox && mailbox->number.valid) {
pri_copy_party_number_to_q931(&number, &mailbox->number);
if (vm_id && vm_id->number.valid) {
pri_copy_party_number_to_q931(&number, &vm_id->number);
q931_copy_number_to_rose(ctrl, &msg.args.etsi.MWIIndicate.controlling_user_number,
&number);
}
@@ -1814,11 +1823,11 @@ static unsigned char *enc_etsi_mwi_indicate_message(struct pri *ctrl, unsigned c
*
* \param ctrl D channel controller.
* \param call Call leg to queue message.
* \param mailbox Controlling party number (NULL if not present).
* \param vm_id Voicemail system number (NULL if not present).
* \param basic_service Basic service enum (-1 if not present).
* \param num_messages NumberOfMessages (-1 if not present).
* \param caller_id Controlling party privided number (NULL if not present).
* \param timestamp Generalized Time format (NULL if not present).
* \param caller_id Party leaving message (NULL if not present).
* \param timestamp When message left. (Generalized Time format, NULL if not present)
* \param message_reference Message reference number (-1 if not present).
* \param message_status Message status: added(0), removed(1).
*
@@ -1826,14 +1835,14 @@ static unsigned char *enc_etsi_mwi_indicate_message(struct pri *ctrl, unsigned c
* \retval -1 on error.
*/
static int rose_mwi_indicate_encode(struct pri *ctrl, struct q931_call *call,
const struct pri_party_id *mailbox, int basic_service, int num_messages,
const struct pri_party_id *vm_id, int basic_service, int num_messages,
const struct pri_party_id *caller_id, const char *timestamp, int message_reference,
int message_status)
{
unsigned char buffer[255];
unsigned char *end;
end = enc_etsi_mwi_indicate_message(ctrl, buffer, buffer + sizeof(buffer), mailbox,
end = enc_etsi_mwi_indicate_message(ctrl, buffer, buffer + sizeof(buffer), vm_id,
basic_service, num_messages, caller_id, timestamp, message_reference,
message_status);
if (!end) {
@@ -1843,11 +1852,13 @@ static int rose_mwi_indicate_encode(struct pri *ctrl, struct q931_call *call,
return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL);
}
int pri_mwi_indicate(struct pri *ctrl, const struct pri_party_id *mailbox,
int basic_service, int num_messages, const struct pri_party_id *caller_id,
const char *timestamp, int message_reference, int message_status)
int pri_mwi_indicate_v2(struct pri *ctrl, const struct pri_party_id *mailbox,
const struct pri_party_id *vm_id, int basic_service, int num_messages,
const struct pri_party_id *caller_id, const char *timestamp, int message_reference,
int message_status)
{
struct q931_call *call;
struct q931_party_id called;
if (!ctrl) {
return -1;
@@ -1859,7 +1870,7 @@ int pri_mwi_indicate(struct pri *ctrl, const struct pri_party_id *mailbox,
if (!BRI_NT_PTMP(ctrl)) {
return -1;
}
call = PRI_MASTER(ctrl)->dummy_call;
call = ctrl->link.dummy_call;
if (!call) {
return -1;
}
@@ -1868,9 +1879,11 @@ int pri_mwi_indicate(struct pri *ctrl, const struct pri_party_id *mailbox,
return -1;
}
if (rose_mwi_indicate_encode(ctrl, call, mailbox, basic_service, num_messages,
pri_copy_party_id_to_q931(&called, mailbox);
q931_party_id_fixup(ctrl, &called);
if (rose_mwi_indicate_encode(ctrl, call, vm_id, basic_service, num_messages,
caller_id, timestamp, message_reference, message_status)
|| q931_facility(ctrl, call)) {
|| q931_facility_called(ctrl, call, &called)) {
pri_message(ctrl,
"Could not schedule facility message for MWI indicate message.\n");
return -1;
@@ -1878,6 +1891,14 @@ int pri_mwi_indicate(struct pri *ctrl, const struct pri_party_id *mailbox,
return 0;
}
int pri_mwi_indicate(struct pri *ctrl, const struct pri_party_id *mailbox,
int basic_service, int num_messages, const struct pri_party_id *caller_id,
const char *timestamp, int message_reference, int message_status)
{
return pri_mwi_indicate_v2(ctrl, mailbox, mailbox, basic_service, num_messages,
caller_id, timestamp, message_reference, message_status);
}
/* End MWI */
/* EECT functions */
@@ -1907,7 +1928,7 @@ static unsigned char *enc_ni2_initiate_transfer(struct pri *ctrl, unsigned char
msg.operation = ROSE_NI2_InitiateTransfer;
msg.invoke_id = get_invokeid(ctrl);
/* Let's do the trickery to make sure the flag is correct */
msg.args.ni2.InitiateTransfer.call_reference = call->cr ^ 0x8000;
msg.args.ni2.InitiateTransfer.call_reference = call->cr ^ Q931_CALL_REFERENCE_FLAG;
pos = rose_encode_invoke(ctrl, pos, end, &msg);
return pos;
@@ -2556,8 +2577,9 @@ static int etsi_ect_link_id_rsp(enum APDU_CALLBACK_REASON reason, struct pri *ct
switch (reason) {
case APDU_CALLBACK_REASON_MSG_RESULT:
call_2 = q931_find_call(ctrl, apdu->response.user.value);
if (!call_2) {
call_2 = apdu->response.user.ptr;
if (!q931_is_call_valid(ctrl, call_2)) {
/* Call is no longer present. */
break;
}
@@ -2636,7 +2658,7 @@ int etsi_initiate_transfer(struct pri *ctrl, q931_call *call_1, q931_call *call_
response.invoke_id = ctrl->last_invoke;
response.timeout_time = ctrl->timers[PRI_TIMER_T_RESPONSE];
response.callback = etsi_ect_link_id_rsp;
response.user.value = call_2->cr;
response.user.ptr = call_2;
/* Remember that if we queue a facility IE for a facility message we
* have to explicitly send the facility message ourselves */
@@ -3354,8 +3376,18 @@ int pri_call_add_standard_apdus(struct pri *ctrl, q931_call *call)
*/
int send_call_transfer_complete(struct pri *ctrl, q931_call *call, int call_status)
{
if (rose_call_transfer_complete_encode(ctrl, call, call_status)
|| q931_facility(ctrl, call)) {
int status;
status = rose_call_transfer_complete_encode(ctrl, call, call_status);
if (!status) {
if (!call_status && call->local_id.number.valid
&& (ctrl->display_flags.send & PRI_DISPLAY_OPTION_NAME_UPDATE)) {
status = q931_facility_display_name(ctrl, call, &call->local_id.name);
} else {
status = q931_facility(ctrl, call);
}
}
if (status) {
pri_message(ctrl,
"Could not schedule facility message for call transfer completed.\n");
return -1;
@@ -3364,6 +3396,306 @@ int send_call_transfer_complete(struct pri *ctrl, q931_call *call, int call_stat
return 0;
}
/*!
* \internal
* \brief Encode the ETSI RequestSubaddress invoke message.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode the facility ie contents.
* \param end End of facility ie contents encoding data buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
static unsigned char *enc_etsi_request_subaddress(struct pri *ctrl, unsigned char *pos,
unsigned char *end)
{
struct rose_msg_invoke msg;
pos = facility_encode_header(ctrl, pos, end, NULL);
if (!pos) {
return NULL;
}
memset(&msg, 0, sizeof(msg));
msg.operation = ROSE_ETSI_RequestSubaddress;
msg.invoke_id = get_invokeid(ctrl);
pos = rose_encode_invoke(ctrl, pos, end, &msg);
return pos;
}
/*!
* \brief Encode and queue the RequestSubaddress invoke message.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param call Call leg from which to encode message.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int rose_request_subaddress_encode(struct pri *ctrl, struct q931_call *call)
{
unsigned char buffer[256];
unsigned char *end;
switch (ctrl->switchtype) {
case PRI_SWITCH_EUROISDN_E1:
case PRI_SWITCH_EUROISDN_T1:
end = enc_etsi_request_subaddress(ctrl, buffer, buffer + sizeof(buffer));
break;
case PRI_SWITCH_QSIG:
default:
return -1;
}
if (!end) {
return -1;
}
return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL);
}
/*!
* \internal
* \brief Encode the ETSI SubaddressTransfer invoke message.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode the facility ie contents.
* \param end End of facility ie contents encoding data buffer.
* \param call Call leg from which to encode message.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
static unsigned char *enc_etsi_subaddress_transfer(struct pri *ctrl, unsigned char *pos,
unsigned char *end, struct q931_call *call)
{
struct rose_msg_invoke msg;
pos = facility_encode_header(ctrl, pos, end, NULL);
if (!pos) {
return NULL;
}
memset(&msg, 0, sizeof(msg));
msg.operation = ROSE_ETSI_SubaddressTransfer;
msg.invoke_id = get_invokeid(ctrl);
if (!call->local_id.subaddress.valid) {
return NULL;
}
q931_copy_subaddress_to_rose(ctrl, &msg.args.etsi.SubaddressTransfer.subaddress,
&call->local_id.subaddress);
pos = rose_encode_invoke(ctrl, pos, end, &msg);
return pos;
}
/*!
* \internal
* \brief Encode the Q.SIG SubaddressTransfer invoke message.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode the facility ie contents.
* \param end End of facility ie contents encoding data buffer.
* \param call Call leg from which to encode message.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
static unsigned char *enc_qsig_subaddress_transfer(struct pri *ctrl,
unsigned char *pos, unsigned char *end, struct q931_call *call)
{
struct fac_extension_header header;
struct rose_msg_invoke msg;
memset(&header, 0, sizeof(header));
header.nfe_present = 1;
header.nfe.source_entity = 0; /* endPINX */
header.nfe.destination_entity = 0; /* endPINX */
header.interpretation_present = 1;
header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
pos = facility_encode_header(ctrl, pos, end, &header);
if (!pos) {
return NULL;
}
memset(&msg, 0, sizeof(msg));
msg.operation = ROSE_QSIG_SubaddressTransfer;
msg.invoke_id = get_invokeid(ctrl);
if (!call->local_id.subaddress.valid) {
return NULL;
}
q931_copy_subaddress_to_rose(ctrl,
&msg.args.qsig.SubaddressTransfer.redirection_subaddress,
&call->local_id.subaddress);
pos = rose_encode_invoke(ctrl, pos, end, &msg);
return pos;
}
/*!
* \internal
* \brief Encode and queue the SubaddressTransfer invoke message.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param call Call leg from which to encode message.
*
* \retval 0 on success.
* \retval -1 on error.
*/
static int rose_subaddress_transfer_encode(struct pri *ctrl, struct q931_call *call)
{
unsigned char buffer[256];
unsigned char *end;
switch (ctrl->switchtype) {
case PRI_SWITCH_EUROISDN_E1:
case PRI_SWITCH_EUROISDN_T1:
end =
enc_etsi_subaddress_transfer(ctrl, buffer, buffer + sizeof(buffer), call);
break;
case PRI_SWITCH_QSIG:
end =
enc_qsig_subaddress_transfer(ctrl, buffer, buffer + sizeof(buffer), call);
break;
default:
return -1;
}
if (!end) {
return -1;
}
return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL);
}
/*!
* \brief Send a FACILITY SubaddressTransfer.
*
* \param ctrl D channel controller.
* \param call Q.931 call leg
*
* \retval 0 on success.
* \retval -1 on error.
*/
int send_subaddress_transfer(struct pri *ctrl, struct q931_call *call)
{
if (rose_subaddress_transfer_encode(ctrl, call)
|| q931_facility(ctrl, call)) {
pri_message(ctrl,
"Could not schedule facility message for subaddress transfer.\n");
return -1;
}
return 0;
}
/*!
* \internal
* \brief Handle the received RequestSubaddress facility.
*
* \param ctrl D channel controller.
* \param call Q.931 call leg
*
* \return Nothing
*/
static void etsi_request_subaddress(struct pri *ctrl, struct q931_call *call)
{
struct q931_party_name name;
int changed = 0;
switch (call->notify) {
case PRI_NOTIFY_TRANSFER_ACTIVE:
if (q931_party_number_cmp(&call->remote_id.number, &call->redirection_number)) {
/* The remote party number information changed. */
call->remote_id.number = call->redirection_number;
changed = 1;
}
/* Fall through */
case PRI_NOTIFY_TRANSFER_ALERTING:
if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
if (q931_display_name_get(call, &name)) {
if (q931_party_name_cmp(&call->remote_id.name, &name)) {
/* The remote party name information changed. */
call->remote_id.name = name;
changed = 1;
}
}
}
if (call->redirection_number.valid
&& q931_party_number_cmp(&call->remote_id.number, &call->redirection_number)) {
/* The remote party number information changed. */
call->remote_id.number = call->redirection_number;
changed = 1;
}
if (call->remote_id.subaddress.valid) {
/*
* Clear the subaddress as the remote party has been changed.
* Any new subaddress will arrive later.
*/
q931_party_subaddress_init(&call->remote_id.subaddress);
changed = 1;
}
if (changed) {
call->incoming_ct_state = INCOMING_CT_STATE_POST_CONNECTED_LINE;
}
break;
default:
break;
}
/* Send our subaddress back if we have one. */
if (call->local_id.subaddress.valid) {
send_subaddress_transfer(ctrl, call);
}
}
/*!
* \internal
* \brief Handle the received SubaddressTransfer facility subaddress.
*
* \param ctrl D channel controller.
* \param call Q.931 call leg
* \param subaddr Received subaddress of remote party.
*
* \return Nothing
*/
static void handle_subaddress_transfer(struct pri *ctrl, struct q931_call *call, const struct rosePartySubaddress *subaddr)
{
int changed = 0;
struct q931_party_name name;
struct q931_party_subaddress q931_subaddress;
q931_party_subaddress_init(&q931_subaddress);
rose_copy_subaddress_to_q931(ctrl, &q931_subaddress, subaddr);
if (q931_party_subaddress_cmp(&call->remote_id.subaddress, &q931_subaddress)) {
call->remote_id.subaddress = q931_subaddress;
changed = 1;
}
if (call->redirection_number.valid
&& q931_party_number_cmp(&call->remote_id.number, &call->redirection_number)) {
/* The remote party number information changed. */
call->remote_id.number = call->redirection_number;
changed = 1;
}
if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
if (q931_display_name_get(call, &name)) {
if (q931_party_name_cmp(&call->remote_id.name, &name)) {
/* The remote party name information changed. */
call->remote_id.name = name;
changed = 1;
}
}
}
if (changed) {
call->incoming_ct_state = INCOMING_CT_STATE_POST_CONNECTED_LINE;
}
}
/*!
* \internal
* \brief Encode a plain facility ETSI error code.
@@ -3632,7 +3964,7 @@ int pri_rerouting_rsp(struct pri *ctrl, q931_call *call, int invoke_id, enum PRI
{
enum rose_error_code rose_err;
if (!ctrl || !call) {
if (!ctrl || !pri_is_call_valid(ctrl, call)) {
return -1;
}
@@ -3640,7 +3972,12 @@ int pri_rerouting_rsp(struct pri *ctrl, q931_call *call, int invoke_id, enum PRI
rose_err = ROSE_ERROR_Gen_ResourceUnavailable;
switch (code) {
case PRI_REROUTING_RSP_OK_CLEAR:
return rose_result_ok_encode(ctrl, call, Q931_DISCONNECT, invoke_id);
/*
* Send the response out on the next message which should be
* either Q931_DISCONNECT or Q931_RELEASE depending upon who
* initiates the disconnect first.
*/
return rose_result_ok_encode(ctrl, call, Q931_ANY_MESSAGE, invoke_id);
case PRI_REROUTING_RSP_OK_RETAIN:
return send_facility_result_ok(ctrl, call, invoke_id);
case PRI_REROUTING_RSP_NOT_SUBSCRIBED:
@@ -3673,7 +4010,7 @@ int pri_rerouting_rsp(struct pri *ctrl, q931_call *call, int invoke_id, enum PRI
int pri_transfer_rsp(struct pri *ctrl, q931_call *call, int invoke_id, int is_successful)
{
if (!ctrl || !call) {
if (!ctrl || !pri_is_call_valid(ctrl, call)) {
return -1;
}
@@ -3804,7 +4141,7 @@ static int rose_mcid_req_encode(struct pri *ctrl, q931_call *call)
int pri_mcid_req_send(struct pri *ctrl, q931_call *call)
{
if (!ctrl || !call) {
if (!ctrl || !pri_is_call_valid(ctrl, call)) {
return -1;
}
if (call->cc.originated) {
@@ -3824,7 +4161,6 @@ int pri_mcid_req_send(struct pri *ctrl, q931_call *call)
void pri_mcid_enable(struct pri *ctrl, int enable)
{
if (ctrl) {
ctrl = PRI_MASTER(ctrl);
ctrl->mcid_support = enable ? 1 : 0;
}
}
@@ -3881,7 +4217,7 @@ void rose_handle_reject(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
* Look for the original invocation message on the
* broadcast dummy call reference call first.
*/
orig_call = PRI_MASTER(ctrl)->dummy_call;
orig_call = ctrl->link.dummy_call;
if (orig_call) {
apdu = pri_call_apdu_find(orig_call, reject->invoke_id);
}
@@ -3965,7 +4301,7 @@ void rose_handle_error(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *
* Look for the original invocation message on the
* broadcast dummy call reference call first.
*/
orig_call = PRI_MASTER(ctrl)->dummy_call;
orig_call = ctrl->link.dummy_call;
if (orig_call) {
apdu = pri_call_apdu_find(orig_call, error->invoke_id);
}
@@ -4041,7 +4377,7 @@ void rose_handle_result(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
* Look for the original invocation message on the
* broadcast dummy call reference call first.
*/
orig_call = PRI_MASTER(ctrl)->dummy_call;
orig_call = ctrl->link.dummy_call;
if (orig_call) {
apdu = pri_call_apdu_find(orig_call, result->invoke_id);
}
@@ -4098,7 +4434,7 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
break;
#endif /* Not handled yet */
case ROSE_ETSI_CallDeflection:
if (!PRI_MASTER(ctrl)->deflection_support) {
if (!ctrl->deflection_support) {
send_facility_error(ctrl, call, invoke->invoke_id,
ROSE_ERROR_Gen_NotSubscribed);
break;
@@ -4166,7 +4502,7 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
&deflection);
break;
case ROSE_ETSI_CallRerouting:
if (!PRI_MASTER(ctrl)->deflection_support) {
if (!ctrl->deflection_support) {
send_facility_error(ctrl, call, invoke->invoke_id,
ROSE_ERROR_Gen_NotSubscribed);
break;
@@ -4238,8 +4574,7 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
party_id.number.presentation =
PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
} else {
party_id.number.presentation =
PRI_PRES_UNAVAILABLE | PRI_PRES_USER_NUMBER_UNSCREENED;
party_id.number.presentation = PRES_NUMBER_NOT_AVAILABLE;
}
} else {
q931_party_number_init(&party_id.number);
@@ -4364,7 +4699,7 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
break;
#endif /* Not handled yet */
case ROSE_ETSI_EctExecute:
if (!PRI_MASTER(ctrl)->transfer_support) {
if (!ctrl->transfer_support) {
send_facility_error(ctrl, call, invoke->invoke_id,
ROSE_ERROR_Gen_NotSubscribed);
break;
@@ -4382,14 +4717,14 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
}
break;
case ROSE_ETSI_RequestSubaddress:
/* Ignore since we are not handling subaddresses yet. */
etsi_request_subaddress(ctrl, call);
break;
#if 0 /* Not handled yet */
case ROSE_ETSI_SubaddressTransfer:
handle_subaddress_transfer(ctrl, call,
&invoke->args.etsi.SubaddressTransfer.subaddress);
break;
#endif /* Not handled yet */
case ROSE_ETSI_EctLinkIdRequest:
if (!PRI_MASTER(ctrl)->transfer_support) {
if (!ctrl->transfer_support) {
send_facility_error(ctrl, call, invoke->invoke_id,
ROSE_ERROR_Gen_ResourceUnavailable);
break;
@@ -4404,17 +4739,33 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
send_ect_link_id_rsp(ctrl, call, invoke->invoke_id);
break;
case ROSE_ETSI_EctInform:
if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
q931_display_name_get(call, &call->remote_id.name);
}
/* redirectionNumber is put in remote_id.number */
if (invoke->args.etsi.EctInform.redirection_present) {
rose_copy_presented_number_unscreened_to_q931(ctrl,
&call->remote_id.number, &invoke->args.etsi.EctInform.redirection);
}
/*
* Clear the subaddress as the remote party has been changed.
* Any new subaddress will arrive later.
*/
q931_party_subaddress_init(&call->remote_id.subaddress);
if (!invoke->args.etsi.EctInform.status) {
/* The remote party for the transfer has not answered yet. */
call->incoming_ct_state = INCOMING_CT_STATE_EXPECT_CT_ACTIVE;
} else {
call->incoming_ct_state = INCOMING_CT_STATE_POST_CONNECTED_LINE;
}
/* Send our subaddress back if we have one. */
if (call->local_id.subaddress.valid) {
send_subaddress_transfer(ctrl, call);
}
break;
case ROSE_ETSI_EctLoopTest:
/*
@@ -4429,7 +4780,7 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
break;
#endif /* defined(STATUS_REQUEST_PLACE_HOLDER) */
case ROSE_ETSI_CallInfoRetain:
if (!PRI_MASTER(ctrl)->cc_support) {
if (!ctrl->cc_support) {
/*
* Blocking the cc-available event effectively
* disables call completion for outgoing calls.
@@ -4444,7 +4795,7 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
if (!cc_record) {
break;
}
cc_record->signaling = PRI_MASTER(ctrl)->dummy_call;
cc_record->signaling = ctrl->link.dummy_call;
/*
* Since we received this facility, we will not be allocating any
* reference and linkage id's.
@@ -4644,7 +4995,7 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
pri_cc_event(ctrl, call, cc_record, CC_EVENT_REMOTE_USER_FREE);
break;
case ROSE_ETSI_CCBS_T_Available:
if (!PRI_MASTER(ctrl)->cc_support) {
if (!ctrl->cc_support) {
/*
* Blocking the cc-available event effectively
* disables call completion for outgoing calls.
@@ -4668,7 +5019,7 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
/* Don't even dignify this with a response. */
break;
}
if (!PRI_MASTER(ctrl)->mcid_support) {
if (!ctrl->mcid_support) {
send_facility_error(ctrl, call, invoke->invoke_id,
ROSE_ERROR_Gen_NotSubscribed);
break;
@@ -4710,6 +5061,10 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
break;
#endif /* Not handled yet */
case ROSE_QSIG_CallingName:
if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
q931_display_name_get(call, &call->remote_id.name);
}
/* CallingName is put in remote_id.name */
rose_copy_name_to_q931(ctrl, &call->remote_id.name,
&invoke->args.qsig.CallingName.name);
@@ -4731,6 +5086,10 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
}
break;
case ROSE_QSIG_CalledName:
if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
q931_display_name_get(call, &call->remote_id.name);
}
/* CalledName is put in remote_id.name */
rose_copy_name_to_q931(ctrl, &call->remote_id.name,
&invoke->args.qsig.CalledName.name);
@@ -4752,6 +5111,10 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
}
break;
case ROSE_QSIG_ConnectedName:
if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
q931_display_name_get(call, &call->remote_id.name);
}
/* ConnectedName is put in remote_id.name */
rose_copy_name_to_q931(ctrl, &call->remote_id.name,
&invoke->args.qsig.ConnectedName.name);
@@ -4803,6 +5166,10 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
break;
#endif /* Not handled yet */
case ROSE_QSIG_CallTransferActive:
if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
q931_display_name_get(call, &call->remote_id.name);
}
call->incoming_ct_state = INCOMING_CT_STATE_POST_CONNECTED_LINE;
/* connectedAddress is put in remote_id */
@@ -4816,6 +5183,10 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
}
break;
case ROSE_QSIG_CallTransferComplete:
if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
q931_display_name_get(call, &call->remote_id.name);
}
/* redirectionNumber is put in remote_id.number */
rose_copy_presented_number_screened_to_q931(ctrl, &call->remote_id.number,
&invoke->args.qsig.CallTransferComplete.redirection);
@@ -4826,16 +5197,31 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
&invoke->args.qsig.CallTransferComplete.redirection_name);
}
/*
* Clear the subaddress as the remote party has been changed.
* Any new subaddress will arrive later.
*/
q931_party_subaddress_init(&call->remote_id.subaddress);
if (invoke->args.qsig.CallTransferComplete.call_status == 1) {
/* The remote party for the transfer has not answered yet. */
call->incoming_ct_state = INCOMING_CT_STATE_EXPECT_CT_ACTIVE;
} else {
call->incoming_ct_state = INCOMING_CT_STATE_POST_CONNECTED_LINE;
}
/* Send our subaddress back if we have one. */
if (call->local_id.subaddress.valid) {
send_subaddress_transfer(ctrl, call);
}
break;
case ROSE_QSIG_CallTransferUpdate:
party_id = call->remote_id;
if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
q931_display_name_get(call, &party_id.name);
}
/* redirectionNumber is put in party_id.number */
rose_copy_presented_number_screened_to_q931(ctrl, &party_id.number,
&invoke->args.qsig.CallTransferUpdate.redirection);
@@ -4858,10 +5244,10 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
}
}
break;
#if 0 /* Not handled yet */
case ROSE_QSIG_SubaddressTransfer:
handle_subaddress_transfer(ctrl, call,
&invoke->args.qsig.SubaddressTransfer.redirection_subaddress);
break;
#endif /* Not handled yet */
case ROSE_QSIG_PathReplacement:
anfpr_pathreplacement_respond(ctrl, call, ie);
break;
@@ -4876,7 +5262,7 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
break;
#endif /* Not handled yet */
case ROSE_QSIG_CallRerouting:
if (!PRI_MASTER(ctrl)->deflection_support) {
if (!ctrl->deflection_support) {
send_facility_error(ctrl, call, invoke->invoke_id,
ROSE_ERROR_Gen_NotSubscribed);
break;
@@ -5167,8 +5553,9 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
#endif /* Not handled yet */
default:
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, "!! ROSE invoke operation not handled! %s\n",
rose_operation2str(invoke->operation));
pri_message(ctrl,
"!! ROSE invoke operation not handled on switchtype:%s! %s\n",
pri_switch2str(ctrl->switchtype), rose_operation2str(invoke->operation));
}
break;
}

View File

@@ -221,6 +221,8 @@ int qsig_cf_callrerouting(struct pri *pri, q931_call *c, const char* dest, const
int send_reroute_request(struct pri *ctrl, q931_call *call, const struct q931_party_id *caller, const struct q931_party_redirecting *deflection, int subscription_option);
int send_call_transfer_complete(struct pri *pri, q931_call *call, int call_status);
int rose_request_subaddress_encode(struct pri *ctrl, struct q931_call *call);
int send_subaddress_transfer(struct pri *ctrl, struct q931_call *call);
int rose_diverting_leg_information1_encode(struct pri *pri, q931_call *call);
int rose_diverting_leg_information3_encode(struct pri *pri, q931_call *call, int messagetype);

View File

@@ -60,6 +60,9 @@ struct pri_sched {
/*! Maximum number of facility ie's to handle per incoming message. */
#define MAX_FACILITY_IES 8
/*! Maximum length of sent display text string. (No null terminator.) */
#define MAX_DISPLAY_TEXT 80
/*! Accumulated pri_message() line until a '\n' is seen on the end. */
struct pri_msg_line {
/*! Accumulated buffer used. */
@@ -76,8 +79,10 @@ struct pri {
void *userdata;
/*! Accumulated pri_message() line. (Valid in master record only) */
struct pri_msg_line *msg_line;
struct pri *subchannel; /* Sub-channel if appropriate */
struct pri *master; /* Master channel if appropriate */
/*! NFAS master/primary channel if appropriate */
struct pri *master;
/*! Next NFAS slaved D channel if appropriate */
struct pri *slave;
struct {
/*! Dynamically allocated array of timers that can grow as needed. */
struct pri_sched *timer;
@@ -85,6 +90,8 @@ struct pri {
unsigned num_slots;
/*! Maximum timer slots currently needed. */
unsigned max_used;
/*! First timer id in this timer pool. */
unsigned first_id;
} sched;
int debug; /* Debug stuff */
int state; /* State of D-channel */
@@ -93,9 +100,9 @@ struct pri {
int localtype; /* Local network type (unknown, network, cpe) */
int remotetype; /* Remote network type (unknown, network, cpe) */
int sapi;
int tei;
int protodisc;
int protodisc; /* Layer 3 protocol discriminator */
unsigned int nfas:1;/* TRUE if this D channel is involved with an NFAS group */
unsigned int bri:1;
unsigned int acceptinbanddisconnect:1; /* Should we allow inband progress after DISCONNECT? */
unsigned int sendfacility:1;
@@ -111,65 +118,35 @@ struct pri {
unsigned int manual_connect_ack:1;/* TRUE if the CONNECT_ACKNOWLEDGE is sent with API call */
unsigned int mcid_support:1;/* TRUE if the upper layer supports MCID */
/* MDL variables */
int mdl_error;
int mdl_error_state;
int mdl_timer;
int mdl_free_me;
/* Q.921 State */
int q921_state;
int RC;
int peer_rx_busy:1;
int own_rx_busy:1;
int acknowledge_pending:1;
int reject_exception:1;
int v_s; /* Next N(S) for transmission */
int v_a; /* Last acknowledged frame */
int v_r; /* Next frame expected to be received */
/*! Layer 2 link control for D channel. */
struct q921_link link;
/*! Layer 2 persistence option. */
enum pri_layer2_persistence l2_persistence;
/*! T201 TEI Identity Check timer. */
int t201_timer;
/*! Number of times T201 has expired. */
int t201_expirycnt;
int cref; /* Next call reference value */
int l3initiated;
/* Various timers */
int t203_timer; /* Max idle time */
int t202_timer;
int n202_counter;
int ri;
int t200_timer; /* T-200 retransmission timer */
/* All ISDN Timer values */
int timers[PRI_MAX_TIMERS];
/* Used by scheduler */
struct timeval tv;
int schedev;
pri_event ev; /* Static event thingy */
/*! Subcommands for static event thingy. */
struct pri_subcommands subcmds;
/* Q.921 Re-transmission queue */
struct q921_frame *txqueue;
/* Q.931 calls */
q931_call **callpool;
q931_call *localpool;
struct q931_call **callpool;
struct q931_call *localpool;
/*!
* \brief Q.931 Dummy call reference call associated with this TEI.
* \note If present then this call is allocated as part of the
* D channel control structure.
*/
q931_call *dummy_call;
#ifdef LIBPRI_COUNTERS
/* q921/q931 packet counters */
unsigned int q921_txcount;
unsigned int q921_rxcount;
unsigned int q931_txcount;
unsigned int q931_rxcount;
#endif
short last_invoke; /* Last ROSE invoke ID (Valid in master record only) */
@@ -207,6 +184,15 @@ struct pri {
/*! Number of facility ie's in the array from the current received message. */
unsigned char count;
} facility;
/*! Display text policy handling options. */
struct {
/*! Send display text policy option flags. */
unsigned long send;
/*! Receive display text policy option flags. */
unsigned long receive;
} display_flags;
/*! Configured date/time ie send policy option. */
int date_time_send;
};
/*! \brief Maximum name length plus null terminator (From ECMA-164) */
@@ -369,10 +355,6 @@ struct pri_sr {
int aoc_charging_request;
};
/* Internal switch types */
#define PRI_SWITCH_GR303_EOC_PATH 19
#define PRI_SWITCH_GR303_TMC_SWITCHING 20
#define Q931_MAX_TEI 8
/*! \brief Incoming call transfer states. */
@@ -447,9 +429,10 @@ struct decoded_bc {
/* q931_call datastructure */
struct q931_call {
struct pri *pri; /* PRI */
struct pri *pri; /* D channel controller (master) */
struct q921_link *link; /* Q.921 link associated with this call. */
struct q931_call *next;
int cr; /* Call Reference */
q931_call *next;
/* Slotmap specified (bitmap of channels 31/24-1) (Channel Identifier IE) (-1 means not specified) */
int slotmap;
/* An explicit channel (Channel Identifier IE) (-1 means not specified) */
@@ -563,9 +546,9 @@ struct q931_call {
/*! \brief Incoming call transfer state. */
enum INCOMING_CT_STATE incoming_ct_state;
/*! Call hold supplementary state. */
/*! Call hold supplementary state. Valid on master call record only. */
enum Q931_HOLD_STATE hold_state;
/*! Call hold event timer */
/*! Call hold event timer. Valid on master call record only. */
int hold_timer;
int deflection_in_progress; /*!< CallDeflection for NT PTMP in progress. */
@@ -590,7 +573,7 @@ struct q931_call {
int is_link_id_valid;
/* Bridged call info */
q931_call *bridged_call; /* Pointer to other leg of bridged call (Used by Q.SIG when eliminating tromboned calls) */
struct q931_call *bridged_call; /* Pointer to other leg of bridged call (Used by Q.SIG when eliminating tromboned calls) */
int changestatus; /* SERVICE message changestatus */
int reversecharge; /* Reverse charging indication:
@@ -599,11 +582,14 @@ struct q931_call {
0,2-7 - Reserved for future use */
int t303_timer;
int t303_expirycnt;
int t312_timer;
int fake_clearing_timer;
int hangupinitiated;
/*! \brief TRUE if we broadcast this call's SETUP message. */
int outboundbroadcast;
int performing_fake_clearing;
/*! TRUE if the master call is processing a hangup. Don't destroy it now. */
int master_hanging_up;
/*!
* \brief Master call controlling this call.
* \note Always valid. Master and normal calls point to self.
@@ -636,8 +622,56 @@ struct q931_call {
unsigned char initially_redirected;
} cc;
/*! Display text ie contents. */
struct {
/*! Display ie text. NULL if not present or consumed as remote name. */
const unsigned char *text;
/*! Full IE code of received display text */
int full_ie;
/*! Length of display text. */
unsigned char length;
/*!
* \brief Character set the text is using.
* \details
* unknown(0),
* iso8859-1(1),
* enum-value-withdrawn-by-ITU-T(2)
* iso8859-2(3),
* iso8859-3(4),
* iso8859-4(5),
* iso8859-5(6),
* iso8859-7(7),
* iso10646-BmpString(8),
* iso10646-utf-8String(9)
*/
unsigned char char_set;
} display;
/* AOC charge requesting on Setup */
int aoc_charging_request;
unsigned int slotmap_size:1;/* TRUE if the slotmap is E1 (32 bits). */
/*! Control the RESTART reception to the upper layer. */
struct {
/*! Timer ID of RESTART notification events to upper layer. */
int timer;
/*! Current RESTART notification index. */
int idx;
/*! Number of channels in the channel ID list. */
int count;
/*! Channel ID list */
char chan_no[32];
} restart;
/*! Control the RESTART retransmissions. */
struct {
/*! T316 RESTART retransmit timer. */
int t316_timer;
/*! Number of times remaining that RESTART can be transmitted. */
int remain;
/*! Encoded RESTART channel id. */
int channel;
} restart_tx;
};
enum CC_STATES {
@@ -699,6 +733,8 @@ enum CC_EVENTS {
CC_EVENT_LINK_CANCEL,
/*! Tear down CC request from upper layer. */
CC_EVENT_CANCEL,
/*! Abnormal clearing of original call. (T309 processing/T309 timeout/TEI removal) */
CC_EVENT_INTERNAL_CLEARING,
/*! Received message indicating tear down of CC signaling link completed. */
CC_EVENT_SIGNALING_GONE,
/*! Delayed hangup request for the signaling link to allow subcmd events to be passed up. */
@@ -744,8 +780,8 @@ enum CC_PARTY_A_AVAILABILITY {
struct pri_cc_record {
/*! Next call-completion record in the list */
struct pri_cc_record *next;
/*! Master D channel control structure. */
struct pri *master;
/*! D channel control structure. */
struct pri *ctrl;
/*! Original call that is offered CC availability. (NULL if no longer exists.) */
struct q931_call *original_call;
/*!
@@ -881,11 +917,35 @@ struct d_ctrl_dummy {
struct q931_call dummy_call;
};
extern int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data);
/*! Layer 2 link control structure with associated dummy call reference record. */
struct link_dummy {
/*! Layer 2 control structure. Must be first in the structure. */
struct q921_link link;
/*! Dummy call reference call record. */
struct q931_call dummy_call;
};
/*!
* \brief Check if the given call ptr is valid and gripe if not.
*
* \param ctrl D channel controller.
* \param call Q.931 call leg.
*
* \retval TRUE if call ptr is valid.
* \retval FALSE if call ptr is invalid.
*/
#define pri_is_call_valid(ctrl, call) \
q931_is_call_valid_gripe(ctrl, call, __PRETTY_FUNCTION__, __LINE__)
int q931_is_call_valid(struct pri *ctrl, struct q931_call *call);
int q931_is_call_valid_gripe(struct pri *ctrl, struct q931_call *call, const char *func_name, unsigned long func_line);
unsigned pri_schedule_event(struct pri *ctrl, int ms, void (*function)(void *data), void *data);
extern pri_event *pri_schedule_run(struct pri *pri);
extern void pri_schedule_del(struct pri *pri, int ev);
void pri_schedule_del(struct pri *ctrl, unsigned id);
int pri_schedule_check(struct pri *ctrl, unsigned id, void (*function)(void *data), void *data);
extern pri_event *pri_mkerror(struct pri *pri, char *errstr);
@@ -894,10 +954,10 @@ void pri_error(struct pri *ctrl, const char *fmt, ...) __attribute__((format(pri
void libpri_copy_string(char *dst, const char *src, size_t size);
struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata, int tei, int bri);
void __pri_free_tei(struct pri *p);
void pri_link_destroy(struct q921_link *link);
struct q921_link *pri_link_new(struct pri *ctrl, int sapi, int tei);
void q931_init_call_record(struct pri *ctrl, struct q931_call *call, int cr);
void q931_init_call_record(struct q921_link *link, struct q931_call *call, int cr);
void pri_sr_init(struct pri_sr *req);
@@ -945,9 +1005,16 @@ void pri_copy_party_id_to_q931(struct q931_party_id *q931_id, const struct pri_p
void q931_party_id_fixup(const struct pri *ctrl, struct q931_party_id *id);
int q931_party_id_presentation(const struct q931_party_id *id);
int q931_display_name_get(struct q931_call *call, struct q931_party_name *name);
int q931_display_text(struct pri *ctrl, struct q931_call *call, const struct pri_subcmd_display_txt *display);
int q931_facility_display_name(struct pri *ctrl, struct q931_call *call, const struct q931_party_name *name);
int q931_facility_called(struct pri *ctrl, struct q931_call *call, const struct q931_party_id *called);
const char *q931_call_state_str(enum Q931_CALL_STATE callstate);
const char *msg2str(int msg);
int q931_get_subcall_count(struct q931_call *master);
struct q931_call *q931_find_winning_call(struct q931_call *call);
int q931_master_pass_event(struct pri *ctrl, struct q931_call *subcall, int msg_type);
struct pri_subcommand *q931_alloc_subcommand(struct pri *ctrl);
@@ -955,27 +1022,31 @@ struct pri_subcommand *q931_alloc_subcommand(struct pri *ctrl);
struct q931_call *q931_find_link_id_call(struct pri *ctrl, int link_id);
struct q931_call *q931_find_held_active_call(struct pri *ctrl, struct q931_call *held_call);
int q931_notify_redirection(struct pri *ctrl, q931_call *call, int notify, const struct q931_party_number *number);
int q931_request_subaddress(struct pri *ctrl, struct q931_call *call, int notify, const struct q931_party_name *name, const struct q931_party_number *number);
int q931_subaddress_transfer(struct pri *ctrl, struct q931_call *call);
int q931_notify_redirection(struct pri *ctrl, struct q931_call *call, int notify, const struct q931_party_name *name, const struct q931_party_number *number);
struct pri_cc_record *pri_cc_find_by_reference(struct pri *ctrl, unsigned reference_id);
struct pri_cc_record *pri_cc_find_by_linkage(struct pri *ctrl, unsigned linkage_id);
struct pri_cc_record *pri_cc_find_by_addressing(struct pri *ctrl, const struct q931_party_address *party_a, const struct q931_party_address *party_b, unsigned length, const unsigned char *q931_ies);
struct pri_cc_record *pri_cc_new_record(struct pri *ctrl, q931_call *call);
void pri_cc_qsig_determine_available(struct pri *ctrl, q931_call *call);
const char *pri_cc_fsm_state_str(enum CC_STATES state);
const char *pri_cc_fsm_event_str(enum CC_EVENTS event);
int pri_cc_event(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record, enum CC_EVENTS event);
int q931_cc_timeout(struct pri *ctrl, struct pri_cc_record *cc_record, enum CC_EVENTS event);
void q931_cc_indirect(struct pri *ctrl, struct pri_cc_record *cc_record, void (*func)(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record));
/*!
* \brief Get the master PRI control structure.
* \brief Get the NFAS master PRI control structure.
*
* \param ctrl D channel controller.
*
* \return Master PRI control structure.
* \return NFAS master PRI control structure.
*/
static inline struct pri *PRI_MASTER(struct pri *ctrl)
static inline struct pri *PRI_NFAS_MASTER(struct pri *ctrl)
{
while (ctrl->master) {
if (ctrl->master) {
ctrl = ctrl->master;
}
return ctrl;
@@ -993,10 +1064,8 @@ static inline int BRI_NT_PTMP(const struct pri *ctrl)
{
struct pri *my_ctrl = (struct pri *) ctrl;
/* Check master control structure */
my_ctrl = PRI_MASTER(my_ctrl);
return my_ctrl->bri && my_ctrl->localtype == PRI_NETWORK
&& my_ctrl->tei == Q921_TEI_GROUP;
&& my_ctrl->link.tei == Q921_TEI_GROUP;
}
/*!
@@ -1011,10 +1080,8 @@ static inline int BRI_TE_PTMP(const struct pri *ctrl)
{
struct pri *my_ctrl = (struct pri *) ctrl;
/* Check master control structure */
my_ctrl = PRI_MASTER(my_ctrl);
return my_ctrl->bri && my_ctrl->localtype == PRI_CPE
&& my_ctrl->tei == Q921_TEI_GROUP;
&& my_ctrl->link.tei == Q921_TEI_GROUP;
}
/*!
@@ -1029,8 +1096,6 @@ static inline int NT_MODE(const struct pri *ctrl)
{
struct pri *my_ctrl = (struct pri *) ctrl;
/* Check master control structure */
my_ctrl = PRI_MASTER(my_ctrl);
return my_ctrl->localtype == PRI_NETWORK;
}
@@ -1046,8 +1111,6 @@ static inline int TE_MODE(const struct pri *ctrl)
{
struct pri *my_ctrl = (struct pri *) ctrl;
/* Check master control structure */
my_ctrl = PRI_MASTER(my_ctrl);
return my_ctrl->localtype == PRI_CPE;
}
@@ -1063,9 +1126,7 @@ static inline int PTP_MODE(const struct pri *ctrl)
{
struct pri *my_ctrl = (struct pri *) ctrl;
/* Check master control structure */
my_ctrl = PRI_MASTER(my_ctrl);
return my_ctrl->tei == Q921_TEI_PRI;
return my_ctrl->link.tei == Q921_TEI_PRI;
}
/*!
@@ -1080,9 +1141,7 @@ static inline int PTMP_MODE(const struct pri *ctrl)
{
struct pri *my_ctrl = (struct pri *) ctrl;
/* Check master control structure */
my_ctrl = PRI_MASTER(my_ctrl);
return my_ctrl->tei == Q921_TEI_GROUP;
return my_ctrl->link.tei == Q921_TEI_GROUP;
}
#define Q931_DUMMY_CALL_REFERENCE -1
@@ -1094,14 +1153,13 @@ static inline int PTMP_MODE(const struct pri *ctrl)
* \retval TRUE if given call is a dummy call.
* \retval FALSE otherwise.
*/
static inline int q931_is_dummy_call(const q931_call *call)
static inline int q931_is_dummy_call(const struct q931_call *call)
{
return (call->cr == Q931_DUMMY_CALL_REFERENCE) ? 1 : 0;
}
static inline short get_invokeid(struct pri *ctrl)
{
ctrl = PRI_MASTER(ctrl);
return ++ctrl->last_invoke;
}

View File

@@ -57,6 +57,8 @@
#define Q921_TEI_GR303_EOC_OPS 4
#define Q921_TEI_GR303_TMC_SWITCHING 0
#define Q921_TEI_GR303_TMC_CALLPROC 0
#define Q921_TEI_AUTO_FIRST 64
#define Q921_TEI_AUTO_LAST 126
#define Q921_SAPI_CALL_CTRL 0
#define Q921_SAPI_GR303_EOC 1
@@ -69,13 +71,16 @@
#define Q921_SAPI_LAYER2_MANAGEMENT 63
#define Q921_TEI_IDENTITY_REQUEST 1
#define Q921_TEI_IDENTITY_ASSIGNED 2
#define Q921_TEI_IDENTITY_DENIED 3
#define Q921_TEI_IDENTITY_CHECK_REQUEST 4
#define Q921_TEI_IDENTITY_CHECK_RESPONSE 5
#define Q921_TEI_IDENTITY_REMOVE 6
#define Q921_TEI_IDENTITY_VERIFY 7
/*! Q.921 TEI management message type */
enum q921_tei_identity {
Q921_TEI_IDENTITY_REQUEST = 1,
Q921_TEI_IDENTITY_ASSIGNED = 2,
Q921_TEI_IDENTITY_DENIED = 3,
Q921_TEI_IDENTITY_CHECK_REQUEST = 4,
Q921_TEI_IDENTITY_CHECK_RESPONSE = 5,
Q921_TEI_IDENTITY_REMOVE = 6,
Q921_TEI_IDENTITY_VERIFY = 7,
};
typedef struct q921_header {
#if __BYTE_ORDER == __BIG_ENDIAN
@@ -158,11 +163,17 @@ typedef union {
struct q921_header h;
} q921_h;
enum q921_tx_frame_status {
Q921_TX_FRAME_NEVER_SENT,
Q921_TX_FRAME_PUSHED_BACK,
Q921_TX_FRAME_SENT,
};
typedef struct q921_frame {
struct q921_frame *next; /* Next in list */
int len; /* Length of header + body */
int transmitted; /* Have we been transmitted */
q921_i h;
struct q921_frame *next; /*!< Next in list */
int len; /*!< Length of header + body */
enum q921_tx_frame_status status; /*!< Tx frame status */
q921_i h; /*!< Actual frame contents. */
} q921_frame;
#define Q921_INC(j) (j) = (((j) + 1) % 128)
@@ -180,24 +191,101 @@ typedef enum q921_state {
Q921_TIMER_RECOVERY = 8,
} q921_state;
/*! TEI identity check procedure states. */
enum q921_tei_check_state {
/*! Not participating in the TEI check procedure. */
Q921_TEI_CHECK_NONE,
/*! No reply to TEI check received. */
Q921_TEI_CHECK_DEAD,
/*! Reply to TEI check received in current poll. */
Q921_TEI_CHECK_REPLY,
/*! No reply to current TEI check poll received. A previous poll got a reply. */
Q921_TEI_CHECK_DEAD_REPLY,
};
/*! \brief Q.921 link controller structure */
struct q921_link {
/*! Next Q.921 link in the chain. */
struct q921_link *next;
/*! D channel controller associated with this link. */
struct pri *ctrl;
/*!
* \brief Q.931 Dummy call reference call associated with this TEI.
*
* \note If present then this call is allocated with the D
* channel control structure or the link control structure
* unless this is the TE PTMP broadcast TEI or a GR303 link.
*/
struct q931_call *dummy_call;
/*! Q.921 Re-transmission queue */
struct q921_frame *tx_queue;
/*! Q.921 State */
enum q921_state state;
/*! TEI identity check procedure state. */
enum q921_tei_check_state tei_check;
/*! Service Access Profile Identifier (SAPI) of this link */
int sapi;
/*! Terminal Endpoint Identifier (TEI) of this link */
int tei;
/*! TEI assignment random indicator. */
int ri;
/*! V(A) - Next I-frame sequence number needing ack */
int v_a;
/*! V(S) - Next I-frame sequence number to send */
int v_s;
/*! V(R) - Next I-frame sequence number expected to receive */
int v_r;
/* Various timers */
/*! T-200 retransmission timer */
int t200_timer;
/*! Retry Count (T200) */
int RC;
int t202_timer;
int n202_counter;
/*! Max idle time */
int t203_timer;
/*! Layer 2 persistence restart delay timer */
int restart_timer;
/* MDL variables */
int mdl_timer;
int mdl_error;
unsigned int mdl_free_me:1;
unsigned int peer_rx_busy:1;
unsigned int own_rx_busy:1;
unsigned int acknowledge_pending:1;
unsigned int reject_exception:1;
unsigned int l3_initiated:1;
};
static inline int Q921_ADD(int a, int b)
{
return (a + b) % 128;
}
/* Dumps a *known good* Q.921 packet */
extern void q921_dump(struct pri *pri, q921_h *h, int len, int showraw, int txrx);
extern void q921_dump(struct pri *pri, q921_h *h, int len, int debugflags, int txrx);
/* Bring up the D-channel */
extern void q921_start(struct pri *pri);
void q921_start(struct q921_link *link);
void q921_bring_layer2_up(struct pri *ctrl);
//extern void q921_reset(struct pri *pri, int reset_iqueue);
extern pri_event *q921_receive(struct pri *pri, q921_h *h, int len);
extern int q921_transmit_iframe(struct pri *pri, int tei, void *buf, int len, int cr);
int q921_transmit_iframe(struct q921_link *link, void *buf, int len, int cr);
extern int q921_transmit_uiframe(struct pri *pri, void *buf, int len);
int q921_transmit_uiframe(struct q921_link *link, void *buf, int len);
extern pri_event *q921_dchannel_up(struct pri *pri);

View File

@@ -443,6 +443,8 @@ enum Q931_RANKED_CALL_STATE {
Q931_RANKED_CALL_STATE_CONNECT,
/*! Call is in some non-call establishment state (likely disconnecting). */
Q931_RANKED_CALL_STATE_OTHER,
/*! Master call is aborting. */
Q931_RANKED_CALL_STATE_ABORT,
};
/* EuroISDN */
@@ -450,13 +452,11 @@ enum Q931_RANKED_CALL_STATE {
extern int maintenance_service(struct pri *pri, int span, int channel, int changestatus);
extern int maintenance_service_ack(struct pri *pri, q931_call *call);
/* Q.SIG specific */
#define QSIG_IE_TRANSIT_COUNT 0x31
extern int q931_receive(struct pri *pri, int tei, q931_h *h, int len);
int q931_receive(struct q921_link *link, q931_h *h, int len);
extern int q931_alerting(struct pri *pri, q931_call *call, int channel, int info);
@@ -491,8 +491,7 @@ extern int q931_call_getcrv(struct pri *pri, q931_call *call, int *callmode);
extern int q931_call_setcrv(struct pri *pri, q931_call *call, int crv, int callmode);
struct q931_call *q931_find_call(struct pri *ctrl, int cr);
struct q931_call *q931_new_call(struct pri *pri);
struct q931_call *q931_new_call(struct pri *ctrl);
extern int q931_setup(struct pri *pri, q931_call *c, struct pri_sr *req);
@@ -502,7 +501,15 @@ void q931_dump(struct pri *ctrl, int tei, q931_h *h, int len, int txrx);
void q931_destroycall(struct pri *pri, q931_call *c);
extern void q931_dl_indication(struct pri *pri, int event);
enum Q931_DL_EVENT {
Q931_DL_EVENT_NONE,
Q931_DL_EVENT_DL_ESTABLISH_IND,
Q931_DL_EVENT_DL_ESTABLISH_CONFIRM,
Q931_DL_EVENT_DL_RELEASE_IND,
Q931_DL_EVENT_DL_RELEASE_CONFIRM,
Q931_DL_EVENT_TEI_REMOVAL,
};
void q931_dl_event(struct q921_link *link, enum Q931_DL_EVENT event);
int q931_send_hold(struct pri *ctrl, struct q931_call *call);
int q931_send_hold_ack(struct pri *ctrl, struct q931_call *call);

View File

@@ -42,7 +42,7 @@
#include <sys/ioctl.h>
#include <sys/select.h>
#include <sys/types.h>
#include <zaptel/zaptel.h>
#include <dahdi/user.h>
#include "libpri.h"
#include "pri_q921.h"
#include "pri_q931.h"
@@ -50,18 +50,18 @@
static int pri_open(char *dev)
{
int dfd;
struct zt_params p;
struct dahdi_params p;
dfd = open(dev, O_RDWR);
if (dfd < 0) {
fprintf(stderr, "Failed to open dchannel '%s': %s\n", dev, strerror(errno));
return -1;
}
if (ioctl(dfd, ZT_GET_PARAMS, &p)) {
if (ioctl(dfd, DAHDI_GET_PARAMS, &p)) {
fprintf(stderr, "Unable to get parameters on '%s': %s\n", dev, strerror(errno));
return -1;
}
if ((p.sigtype != ZT_SIG_HDLCRAW) && (p.sigtype != ZT_SIG_HDLCFCS)) {
if ((p.sigtype != DAHDI_SIG_HDLCRAW) && (p.sigtype != DAHDI_SIG_HDLCFCS)) {
fprintf(stderr, "%s is in %d signalling, not FCS HDLC or RAW HDLC mode\n", dev, p.sigtype);
return -1;
}
@@ -71,7 +71,7 @@ static int pri_open(char *dev)
static void dump_packet(struct pri *pri, char *buf, int len, int txrx)
{
q921_h *h = (q921_h *)buf;
q921_dump(pri, h, len, 1, txrx);
q921_dump(pri, h, len, PRI_DEBUG_ALL, txrx);
if (!((h->h.data[0] & Q921_FRAMETYPE_MASK) & 0x3)) {
q931_dump(pri, h->h.tei, (q931_h *)(h->i.data), len - 4 - 2 /* FCS */, txrx);
}
@@ -80,7 +80,7 @@ static void dump_packet(struct pri *pri, char *buf, int len, int txrx)
}
static int pri_bridge(int d1, int d2)
static void pri_bridge(int d1, int d2)
{
char buf[1024];
fd_set fds;
@@ -94,8 +94,8 @@ static int pri_bridge(int d1, int d2)
max = d1;
if (max < d2)
max = d2;
ioctl(d1, ZT_GETEVENT, &e);
ioctl(d2, ZT_GETEVENT, &e);
ioctl(d1, DAHDI_GETEVENT, &e);
ioctl(d2, DAHDI_GETEVENT, &e);
res = select(max + 1, &fds, NULL, NULL, NULL);
if (res < 0) {
fprintf(stderr, "Select returned %d: %s\n", res, strerror(errno));

View File

@@ -38,13 +38,15 @@
/*! Initial number of scheduled timer slots. */
#define SCHED_EVENTS_INITIAL 128
/*!
* Maximum number of scheduled timer slots.
* Should be a power of 2 multiple of SCHED_EVENTS_INITIAL.
* \brief Maximum number of scheduled timer slots.
* \note Should be a power of 2 and at least SCHED_EVENTS_INITIAL.
*/
#define SCHED_EVENTS_MAX 8192
/*! \brief The maximum number of timers that were active at once. */
static unsigned maxsched = 0;
/*! Last pool id */
static unsigned pool_id = 0;
/* Scheduler routines */
@@ -87,6 +89,23 @@ static int pri_schedule_grow(struct pri *ctrl)
memcpy(timers, ctrl->sched.timer,
ctrl->sched.num_slots * sizeof(struct pri_sched));
free(ctrl->sched.timer);
} else {
/* Creating the timer pool. */
pool_id += SCHED_EVENTS_MAX;
if (pool_id < SCHED_EVENTS_MAX
|| pool_id + (SCHED_EVENTS_MAX - 1) < SCHED_EVENTS_MAX) {
/*
* Not likely to happen.
*
* Timer id's may be aliased if this D channel is used in an
* NFAS group with redundant D channels. Another D channel in
* the group may have the same pool_id.
*/
pri_error(ctrl,
"Pool_id wrapped. Please ignore if you are not using NFAS with backup D channels.\n");
pool_id = SCHED_EVENTS_MAX;
}
ctrl->sched.first_id = pool_id;
}
/* Put the new timer table in place. */
@@ -106,15 +125,12 @@ static int pri_schedule_grow(struct pri *ctrl)
* \retval 0 if scheduler table is full and could not schedule the event.
* \retval id Scheduled event id.
*/
int pri_schedule_event(struct pri *ctrl, int ms, void (*function)(void *data), void *data)
unsigned pri_schedule_event(struct pri *ctrl, int ms, void (*function)(void *data), void *data)
{
unsigned max_used;
unsigned x;
struct timeval tv;
/* Scheduling runs on master channels only */
ctrl = PRI_MASTER(ctrl);
max_used = ctrl->sched.max_used;
for (x = 0; x < max_used; ++x) {
if (!ctrl->sched.timer[x].callback) {
@@ -141,7 +157,7 @@ int pri_schedule_event(struct pri *ctrl, int ms, void (*function)(void *data), v
ctrl->sched.timer[x].when = tv;
ctrl->sched.timer[x].callback = function;
ctrl->sched.timer[x].data = data;
return x + 1;
return ctrl->sched.first_id + x;
}
/*!
@@ -156,9 +172,6 @@ struct timeval *pri_schedule_next(struct pri *ctrl)
struct timeval *closest = NULL;
unsigned x;
/* Scheduling runs on master channels only */
ctrl = PRI_MASTER(ctrl);
/* Scan the scheduled timer slots backwards so we can update the max_used value. */
for (x = ctrl->sched.max_used; x--;) {
if (ctrl->sched.timer[x].callback) {
@@ -196,9 +209,6 @@ static pri_event *__pri_schedule_run(struct pri *ctrl, struct timeval *tv)
void (*callback)(void *);
void *data;
/* Scheduling runs on master channels only */
ctrl = PRI_MASTER(ctrl);
max_used = ctrl->sched.max_used;
for (x = 0; x < max_used; ++x) {
if (ctrl->sched.timer[x].callback
@@ -240,19 +250,73 @@ pri_event *pri_schedule_run(struct pri *ctrl)
* \param ctrl D channel controller.
* \param id Scheduled event id to delete.
* 0 is a disabled/unscheduled event id that is ignored.
* 1 - MAX_SCHED is a valid event id.
*
* \return Nothing
*/
void pri_schedule_del(struct pri *ctrl, int id)
void pri_schedule_del(struct pri *ctrl, unsigned id)
{
/* Scheduling runs on master channels only */
ctrl = PRI_MASTER(ctrl);
struct pri *nfas;
if (0 < id && id <= ctrl->sched.num_slots) {
ctrl->sched.timer[id - 1].callback = NULL;
} else if (id) {
pri_error(ctrl, "Asked to delete sched id %d??? num_slots=%d\n", id,
ctrl->sched.num_slots);
if (!id) {
/* Disabled/unscheduled event id. */
return;
}
if (ctrl->sched.first_id <= id
&& id <= ctrl->sched.first_id + (SCHED_EVENTS_MAX - 1)) {
ctrl->sched.timer[id - ctrl->sched.first_id].callback = NULL;
return;
}
if (ctrl->nfas) {
/* Try to find the timer on another D channel. */
for (nfas = PRI_NFAS_MASTER(ctrl); nfas; nfas = nfas->slave) {
if (nfas->sched.first_id <= id
&& id <= nfas->sched.first_id + (SCHED_EVENTS_MAX - 1)) {
nfas->sched.timer[id - nfas->sched.first_id].callback = NULL;
return;
}
}
}
pri_error(ctrl,
"Asked to delete sched id 0x%08x??? first_id=0x%08x, num_slots=0x%08x\n", id,
ctrl->sched.first_id, ctrl->sched.num_slots);
}
/*!
* \brief Is the scheduled event this callback.
*
* \param ctrl D channel controller.
* \param id Scheduled event id to check.
* 0 is a disabled/unscheduled event id.
* \param function Callback function to call when timeout.
* \param data Value to give callback function when timeout.
*
* \return TRUE if scheduled event has the callback.
*/
int pri_schedule_check(struct pri *ctrl, unsigned id, void (*function)(void *data), void *data)
{
struct pri *nfas;
if (!id) {
/* Disabled/unscheduled event id. */
return 0;
}
if (ctrl->sched.first_id <= id
&& id <= ctrl->sched.first_id + (SCHED_EVENTS_MAX - 1)) {
return ctrl->sched.timer[id - ctrl->sched.first_id].callback == function
&& ctrl->sched.timer[id - ctrl->sched.first_id].data == data;
}
if (ctrl->nfas) {
/* Try to find the timer on another D channel. */
for (nfas = PRI_NFAS_MASTER(ctrl); nfas; nfas = nfas->slave) {
if (nfas->sched.first_id <= id
&& id <= nfas->sched.first_id + (SCHED_EVENTS_MAX - 1)) {
return nfas->sched.timer[id - nfas->sched.first_id].callback == function
&& nfas->sched.timer[id - nfas->sched.first_id].data == data;
}
}
}
pri_error(ctrl,
"Asked to check sched id 0x%08x??? first_id=0x%08x, num_slots=0x%08x\n", id,
ctrl->sched.first_id, ctrl->sched.num_slots);
return 0;
}

View File

@@ -68,7 +68,10 @@ static void do_channel(int fd)
int i=0;
while ((res = read(fd, buf, READ_SIZE)) > 0 && (i++ < 1000)) {
write(fd, buf, res);
if (write(fd, buf, res) == -1) {
fprintf(stderr, "--!! Failed write: %d\n", errno);
break;
}
}
}

2458
q921.c

File diff suppressed because it is too large Load Diff

3063
q931.c

File diff suppressed because it is too large Load Diff

54
rose.c
View File

@@ -1237,6 +1237,34 @@ static const struct rose_convert_msg rose_dms100_msgs[] = {
rose_enc_dms100_RLT_ThirdParty_ARG, NULL,
rose_dec_dms100_RLT_ThirdParty_ARG, NULL
},
/* DMS-100 seems to have pirated some Q.SIG messages */
/*
* localValue's from Q.SIG Name-Operations
* { iso(1) standard(0) pss1-name(13868) name-operations(0) }
*/
{
ROSE_QSIG_CallingName, NULL, 0,
rose_enc_qsig_CallingName_ARG, NULL,
rose_dec_qsig_CallingName_ARG, NULL
},
#if 0 /* ROSE_DMS100_RLT_OPERATION_IND, and ROSE_DMS100_RLT_THIRD_PARTY conflict! */
{
ROSE_QSIG_CalledName, NULL, 1,
rose_enc_qsig_CalledName_ARG, NULL,
rose_dec_qsig_CalledName_ARG, NULL
},
{
ROSE_QSIG_ConnectedName, NULL, 2,
rose_enc_qsig_ConnectedName_ARG, NULL,
rose_dec_qsig_ConnectedName_ARG, NULL
},
{
ROSE_QSIG_BusyName, NULL, 3,
rose_enc_qsig_BusyName_ARG, NULL,
rose_dec_qsig_BusyName_ARG, NULL
},
#endif
/* *INDENT-ON* */
};
@@ -1292,6 +1320,19 @@ static const struct rose_convert_msg rose_ni2_msgs[] = {
* encode_invoke_args, encode_result_args,
* decode_invoke_args, decode_result_args
*/
{
ROSE_NI2_InformationFollowing, &rose_ni2_oid, 4,
rose_enc_ni2_InformationFollowing_ARG, NULL,
rose_dec_ni2_InformationFollowing_ARG, NULL
},
/* Also used by PRI_SWITCH_ATT4ESS and PRI_SWITCH_LUCENT5E */
{
ROSE_NI2_InitiateTransfer, &rose_ni2_oid, 8,
rose_enc_ni2_InitiateTransfer_ARG, NULL,
rose_dec_ni2_InitiateTransfer_ARG, NULL
},
/* NI2 seems to have pirated several Q.SIG messages */
/*
* localValue's from Q.SIG Name-Operations
@@ -1317,19 +1358,6 @@ static const struct rose_convert_msg rose_ni2_msgs[] = {
rose_enc_qsig_BusyName_ARG, NULL,
rose_dec_qsig_BusyName_ARG, NULL
},
{
ROSE_NI2_InformationFollowing, &rose_ni2_oid, 4,
rose_enc_ni2_InformationFollowing_ARG, NULL,
rose_dec_ni2_InformationFollowing_ARG, NULL
},
/* Also used by PRI_SWITCH_ATT4ESS and PRI_SWITCH_LUCENT5E */
{
ROSE_NI2_InitiateTransfer, &rose_ni2_oid, 8,
rose_enc_ni2_InitiateTransfer_ARG, NULL,
rose_dec_ni2_InitiateTransfer_ARG, NULL
},
/* *INDENT-ON* */
};

View File

@@ -48,13 +48,10 @@
#include <sys/time.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <zaptel/zaptel.h>
#ifndef SOLARIS
#include <zap.h>
#endif
#include <pthread.h>
#include <sys/select.h>
#include "libpri.h"
#include "pri_q921.h"
#include "pri_q931.h"
#ifndef AF_LOCAL
@@ -66,7 +63,7 @@
#define PRI_DEF_NODETYPE PRI_CPE
#define PRI_DEF_SWITCHTYPE PRI_SWITCH_NI2
static struct pri *first, *cur;
static struct pri *first;
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
@@ -159,9 +156,9 @@ static void testmsg(struct pri *pri, char *s)
*c = '\0';
c++;
}
if (keeplast)
if (keeplast || !pri)
printf("%s", s);
else if (cur == first)
else if (pri == first)
printf("-1 %s", s);
else
printf("-2 %s", s);
@@ -185,9 +182,9 @@ static void testerr(struct pri *pri, char *s)
*c = '\0';
c++;
}
if (keeplast)
if (keeplast || !pri)
printf("%s", s);
else if (cur == first)
else if (pri == first)
printf("=1 %s", s);
else
printf("=2 %s", s);
@@ -207,7 +204,7 @@ static void *dchan(void *data)
/* Joint D-channel */
struct pri *pri = data;
struct timeval *next, tv;
pri_event *e;
pri_event *e = NULL;
fd_set fds;
int res;
for(;;) {
@@ -228,7 +225,6 @@ static void *dchan(void *data)
FD_SET(pri_fd(pri), &fds);
res = select(pri_fd(pri) + 1, &fds, NULL, NULL, next ? &tv : NULL);
pthread_mutex_lock(&lock);
cur = pri;
if (res < 0) {
perror("select");
} else if (!res) {
@@ -238,9 +234,9 @@ static void *dchan(void *data)
}
if (e) {
if (first == pri) {
event1(e->gen.pri, e);
event1(pri, e);
} else {
event2(e->gen.pri, e);
event2(pri, e);
}
}
pthread_mutex_unlock(&lock);