Compare commits

..

35 Commits

Author SHA1 Message Date
Leif Madsen
db3ed3a439 Importing release summary for 1.4.12-beta2 release.
git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.4.12-beta2@1934 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-08-30 20:58:29 +00:00
Leif Madsen
b4621337b6 Importing files for 1.4.12-beta2 release.
git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.4.12-beta2@1933 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-08-30 20:58:27 +00:00
Leif Madsen
ecc75a52aa Creating tag for the release of libpri-1.4.12-beta2
git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.4.12-beta2@1932 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-08-30 20:57:47 +00:00
Richard Mudgett
ab32336b09 Reduced fake MDL-ERROR (Z) message severity to be visible only when debugging enabled.
git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1929 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-08-30 20:49:11 +00:00
Richard Mudgett
0089f4777a Q.921/Q.931 message debug output improvements.
The Q.931 message decode debug output now will follow the correct Q.921
header decode if Q.921 message dumping is enabled.  Also the Q.931 message
decode will happen when the message actually goes out on the line instead
of when Q.931 passes the message to Q.921.  Q.921 may have to request a
TEI, bring the connection up, or retransmit previous frames before it can
actually send the new message.


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1928 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-08-30 20:30:59 +00:00
Richard Mudgett
1fba74a1d5 Q.921 improvements from comparing Q.921 SDL diagrams with implementation.
* Handle sending and receiving DM response frames as needed.

* Added handling of received FRMR frames.

* Completed implementation of Q921_AWAITING_RELEASE state.  (State is
currently unreachable since we have no API to initiate sending the DISC
message.)

* Better NT PTMP TEI allocation.

* Reduced more ERROR level severity messages so users will stop panicking
when they see ERROR.  This is especially true for the Q.921 MDL-ERROR
messages.

* Added better Q.921 visibility when normal debug message level is enabled.


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1923 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-08-30 19:31:46 +00:00
Richard Mudgett
da0b057536 ISDN BRI does not recover from line faults
Q.921 was getting stuck in state 2 (Q921_ASSIGN_AWAITING_TEI).  For some
reason the network was removing the TEI.  Libpri then immediately tried to
get a new TEI assigned.  The network did not reply to the N202(3) attempts
to get a new TEI.  Libpri then just gave up trying but did not leave the
state.  Some paths in Q.921 Figure B.3 were not implemented.

Q.921 now transitions to the Q921_TEI_UNASSIGNED state when the N202 count
is exceeded.  Q.921 will wait there until an incoming or outgoing call is
attempted.

* Fixed initializing the n202_counter.  Not initializing the n202_counter
would cause the Q921_TEI_IDENTITY_REQUEST to unexpectedly not go out and
due to how state transitions were done, Q.921 would get stuck in the
Q921_ASSIGN_AWAITING_TEI state.

* Fixed start T202 timer fail causing Q.921 to get stuck in the
Q921_ASSIGN_AWAITING_TEI state if the network did not respond to the
request.

* Fixed handling of Q921_TEI_IDENTITY_REMOVE to do the MDL-REMOVE
primitive (q921_mdl_remove()) instead of transitioning directly to the
Q921_TEI_UNASSIGNED state.  Necessary state clean-up was not getting done.

* Minor tweaks to q921_mdl_remove().  The worst problem was erroneously
generating an error message.

* Fixed potential for sending I-frames with an invalid TEI.  The I-frame
could have been queued when Q.921 did not have an assigned TEI.

* Fixed testing of the q931_receive() return value when a UI-frame is
received.

(closes issue #17570)
Reported by: jcovert
Patches:
      issue17570_v1.4.11.3_v3.patch uploaded by rmudgett (license 664)
      issue17570_v1.4_v3.patch uploaded by rmudgett (license 664)
Tested by: jcovert, rmudgett


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1918 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-08-30 17:53:33 +00:00
Richard Mudgett
e12b0913ec Convert most references of Q931_MAX_TEI to use ARRAY_LEN().
* Minor comment correction in q931_destroycall().
* Redundant logic removal q931_destroycall().
"W && X && (Y || W && Z)" is the same as "W && X && (Y || Z)"


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1912 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-08-27 23:37:46 +00:00
Richard Mudgett
28b3a8f458 Add support to receive ECMA-164 2nd edition OID name ROSE messages.
NOTE: To add support to send the old style name messages will require
implementing them as new ROSE operation message types.

NOTE: To actually use them would likely require implementing another
version of the Q.SIG switch type.  Like (NI1 & NI2) and (4ess & 5ess) for
example.

Patches:
      libpri37.patch uploaded by rmudgett (license 664)

JIRA SWP-2100
JIRA LIBPRI-37


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1904 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-08-27 15:54:17 +00:00
Richard Mudgett
41115a1da6 Make pri_dump_event() only print the event name.
git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1894 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-08-26 23:26:16 +00:00
Richard Mudgett
0cada91336 Added gripe check to rosetest for invalid operation and error codes.
git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1884 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-08-25 17:17:09 +00:00
Richard Mudgett
b612ee46c1 Don't silently fail to post our fake MDL-ERROR(Z).
git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1883 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-08-25 16:38:29 +00:00
Matthew Fredrickson
b83fc0c33f Add silly fake MDL error Z for kicking L2 to reactivate if a DISC or DM is received in proper states on PTP links.
git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1878 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-08-23 22:13:44 +00:00
Richard Mudgett
b2e28bd1e4 No audio on inbound J1 calls.
Incoming calls specifying the channel using a slot map could not negotiate
a B channel correctly.  Libpri historically has handled this as an any
channel request.  However, when chan_dahdi picked a new channel, libpri
sent out the recorded slot map and not the new channel selected.  Thus the
two endpoints would be attached to different B channels and the parties
would not hear anything or would hear the wrong parties.

This patch restores the historical preference of sending out the channel
id using the channel number method if a channel number is available.

JIRA LIBPRI-35
Patches:
      libpri-35_v1.4.11.3.patch uploaded by rmudgett (license 664)
      libpri-35_v1.4.patch uploaded by rmudgett (license 664)
Tested by: rmudgett


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1853 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-08-06 18:35:35 +00:00
Richard Mudgett
9d1fa7f276 Learn (AGAIN!) why state 7 and state 8 transitions were suppressed.
git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1852 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-08-06 18:22:39 +00:00
Richard Mudgett
fc203e3101 Improved Q.921/Q.931 debug output.
* Debug output for a sent Q.931 message in TE PTMP now uses the best
available TEI number instead of always using 127.  It could still be wrong
if layer 2 does not have a TEI assigned.

* Q.921 debug output is grouped better so a decoded message is not split
by a blank line.

* The Q.921 state is also decoded to a name.


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1848 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-08-03 23:04:52 +00:00
Richard Mudgett
5372776ef0 Q921_TIMER_RECOVERY SDL issue in q921_rnr_rx()
Added missing code specified by Q.921 (Figure B.8 Page 85) when receive
RNR in "Timer Recovery" state.

(closes issue #16791)
Reported by: alecdavis
Patches:
      rnr_timer_recovery.diff.txt uploaded by alecdavis (license 585)


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1845 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-08-03 17:33:54 +00:00
Richard Mudgett
589ea41f86 Renamed local struct pri *pri variables to struct pri *ctrl in q921.c.
The context tagging for my editor is much happier now that the struct and
the variable do not have the same name.  (At least for this file.)


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1842 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-08-02 18:47:10 +00:00
Richard Mudgett
4b21faa82d Add pri_new_bri_cb() API - Create BRI D-channel with user defined I/O callbacks and data
There currently exists a pri_new_cb() API call that allows you to create a
PRI with user-defined I/O read and write callbacks, and option userdata.

Add the same capability for BRI interfaces by adding a pri_new_bri_cb()
API function.

(closes issue #16477)
Reported by: nic_bellamy
Patches:
      pri_new_bri_cb_api.patch uploaded by nic bellamy (license 299) (with minor cosmetic changes)


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1836 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-07-22 17:59:57 +00:00
Richard Mudgett
02c5939a33 pritest hadn't been ported to DAHDI
pritest hadn't been ported to DAHDI, made the trivial changes to make it
work.  (I haven't found the equivalent to zap_playf, so changed the
behaviour to an echo box)

(closes issue #17274)
Reported by: horape
Patches:
      pritest.diff uploaded by horape (license 1035) (with minor cosmetic changes)


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1833 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-07-16 22:55:15 +00:00
Richard Mudgett
cf6a952c31 Only need to output one version of the version message.
git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1830 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-07-16 17:20:21 +00:00
Richard Mudgett
14ff4bfad6 Added a libpri version output line as a sanity check for rosetest.
git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1829 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-07-16 17:15:07 +00:00
Richard Mudgett
8c4f87a9e0 Calling name not successfully processed on inbound QSIG PRI calls from Mitel PBX
The alternate form of the Q.SIG Name sequence that allows manufacturer
extensions for CallingName, CalledName, ConnectedName, and BusyName was
not consuming the next ASN.1 tag.  The code that processed the ASN.1 Name
structure was then using a stale tag value.  The stale tag value was then
rejected with the "Did not expect" message.

I have added a test case using the supplied PRI debug output to the
rosetest utility to verify that this alternate encoding is tested in the
future.

(closes issue #17619)
Reported by: jims8650
Patches:
      issue17619_v1.4.11.3.patch uploaded by rmudgett (license 664)
Tested by: rmudgett


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1828 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-07-16 16:37:07 +00:00
Richard Mudgett
c5fce8da41 [regression] Calling Number assignment logic change in libpri 1.4.11.
Restored the old behaviour if there is more than one calling number in the
incoming SETUP message.  A network provided number is reported as ANI.

(closes issue #17495)
Reported by: ibercom
Patches:
      issue_17495_v1.4.11.2.patch uploaded by rmudgett (license 664)
      issue_17495_v1.4.patch uploaded by rmudgett (license 664)
Tested by: ibercom


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1823 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-06-29 16:15:03 +00:00
Richard Mudgett
bf5ef150e6 PRI: XXX Missing handling for mandatory IE 12
The switch is sending the Connected Address ie (12) and there was no
handler for that ie.  That is why the reporter was getting the "Missing
mandatory ie" message.

The simple fix is to just add the missing receive handler for that ie.
Since connected line (COLP) functionality has been added and this is just
an alternate for the Connected Number ie (0x4C), the handler was already
written.  I also changed the ie name to what Q.931 calls it: Connected
Address.

Also some minor code clean up in q931_handle_ie() and ie2str().

JIRA SWP-1678
(closes issue #16915)
Reported by: kobaz


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1818 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-06-25 20:22:23 +00:00
Richard Mudgett
b4375c8aba Q.SIG calling name in FACILITY message not reported to the upper layer.
Q.SIG can send the CallingName, CalledName, and ConnectedName in stand
alone FACILITY messages.  If the CallingName was not sent in the SETUP
message, the caller id name was not reported to the upper layer.

(closes issue #17458)
Reported by: jsmith
Patches:
      issue17458_post_qsig_name.patch uploaded by rmudgett (license 664)
      issue17458_post_qsig_name_v1.4.11.1.patch uploaded by rmudgett (license 664)
Tested by: rmudgett, jsmith


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1810 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-06-04 22:45:59 +00:00
Richard Mudgett
297ff74885 Inband disconnect setting does nothing on BRI spans.
The acceptinbanddisconnect flag is not inherited when creating a new TEI
and thus rendering the setting (and its respective equivalent in Asterisk)
a no-op on BRI setups.

(closes issue #15265)
Reported by: paravoid
Patches:
      inband-bri.diff uploaded by paravoid (license 200)
Tested by: paravoid


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1794 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-06-01 22:59:41 +00:00
Richard Mudgett
505181cc1e Multi component FACILITY messages only process the first component.
The code was only processing the first ROSE component in the facility
message.  I also updated rosetest.c to have a multiple component ROSE
message test.

(closes issue #17428)
Reported by: patrol-cz
Patches:
      issue17428.patch uploaded by rmudgett (license 664)
Tested by: rmudgett, patrol-cz


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1785 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-06-01 16:30:09 +00:00
David Vossel
660609c45b support for sending ETSI advice of charge
Review: https://reviewboard.asterisk.org/r/619/


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1776 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-05-28 22:34:24 +00:00
Richard Mudgett
8c5eeeae79 ETSI Message Waiting Indication (MWI) support.
Add the ability to report waiting messages to ISDN endpoints (phones).

Relevant specification: EN 300 650 and EN 300 745

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


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1767 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-05-28 21:50:14 +00:00
Richard Mudgett
0b28bf0aab ETSI Malicious Call ID support.
Add the ability to report malicious callers.

Relevant specification: EN 300 180

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


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1757 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-05-28 20:26:23 +00:00
Richard Mudgett
e4b8bed7e9 ETSI Call Waiting support.
Add the ability to announce a call to an endpoint when there are no B
channels available.  A call waiting call is a SETUP message with no B
channel selected.

Relevant specification: EN 300 056, EN 300 057, EN 300 058

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


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1746 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-05-28 18:43:57 +00:00
Richard Mudgett
9bb285fdc1 ETSI Advice Of Charge (AOC) event reporting.
This feature passes ETSI AOC-S, AOC-D, and AOC-E message information to
the upper layer (i.e.  Asterisk) for processing.

Relevant specification: EN 300 182

Consideration was made for the possible future addition of Q.SIG AOC
support (ECMA-212) with the events passed to the upper layer.

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


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1737 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-05-28 18:03:38 +00:00
Richard Mudgett
382e7e5c86 Added ETSI Explicit Call Transfer (ECT) support.
Added ability to send and receive ETSI ECT messages to eliminate tromboned
calls.

Added ETSI support to an existing API call to send ECT messages when the
upper level indicates to transfer specified calls.

The libpri API was extended to indicate to the upper layer that the far
end requests the transfer of the indicated calls.

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


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1723 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-05-28 15:19:08 +00:00
Richard Mudgett
6829faae06 Add Call Completion Suppplementary Service
Call Completion Supplementary Service (CCSS) added for the following 
switch types: ETSI PTMP, ETSI PTP, Q.SIG.  

Specifications:
ETS 300 359 CCBS for PTMP and PTP
ETS 301 065 CCNR for PTMP and PTP
ECMA-186 Call Completion for Q.SIG

Several support services were added to support CC:
Dummy Call Reference.
Q.931 REGISTER message.
Dynamic expansion of the number of available timers (up to 8192).
Enhanced facility message handling.

Current implementation limitations preclude the following:
CC service retention is not supported.
Q.SIG path reservation is not supported.

(closes issue #14292)
Reported by: tomaso
Tested by: rmudgett

JIRA SWP-1493

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


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1714 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-05-26 16:01:10 +00:00
39 changed files with 24260 additions and 1566 deletions

View File

@@ -1 +1 @@
1.4.11
1.4.12-beta2

345
ChangeLog
View File

@@ -1,3 +1,348 @@
2010-08-30 Leif Madsen <lmadsen@digium.com>
* libpri 1.4.12-beta2 released.
2010-08-30 20:49 +0000 [r1918-1929] Richard Mudgett <rmudgett@digium.com>
* q921.c: Reduced fake MDL-ERROR (Z) message severity to be visible
only when debugging enabled.
* q921.c, q931.c: Q.921/Q.931 message debug output improvements.
The Q.931 message decode debug output now will follow the correct
Q.921 header decode if Q.921 message dumping is enabled. Also the
Q.931 message decode will happen when the message actually goes
out on the line instead of when Q.931 passes the message to
Q.921. Q.921 may have to request a TEI, bring the connection up,
or retransmit previous frames before it can actually send the new
message.
* q921.c: Q.921 improvements from comparing Q.921 SDL diagrams with
implementation. * Handle sending and receiving DM response frames
as needed. * Added handling of received FRMR frames. * Completed
implementation of Q921_AWAITING_RELEASE state. (State is
currently unreachable since we have no API to initiate sending
the DISC message.) * Better NT PTMP TEI allocation. * Reduced
more ERROR level severity messages so users will stop panicking
when they see ERROR. This is especially true for the Q.921
MDL-ERROR messages. * Added better Q.921 visibility when normal
debug message level is enabled.
* q921.c: ISDN BRI does not recover from line faults Q.921 was
getting stuck in state 2 (Q921_ASSIGN_AWAITING_TEI). For some
reason the network was removing the TEI. Libpri then immediately
tried to get a new TEI assigned. The network did not reply to the
N202(3) attempts to get a new TEI. Libpri then just gave up
trying but did not leave the state. Some paths in Q.921 Figure
B.3 were not implemented. Q.921 now transitions to the
Q921_TEI_UNASSIGNED state when the N202 count is exceeded. Q.921
will wait there until an incoming or outgoing call is attempted.
* Fixed initializing the n202_counter. Not initializing the
n202_counter would cause the Q921_TEI_IDENTITY_REQUEST to
unexpectedly not go out and due to how state transitions were
done, Q.921 would get stuck in the Q921_ASSIGN_AWAITING_TEI
state. * Fixed start T202 timer fail causing Q.921 to get stuck
in the Q921_ASSIGN_AWAITING_TEI state if the network did not
respond to the request. * Fixed handling of
Q921_TEI_IDENTITY_REMOVE to do the MDL-REMOVE primitive
(q921_mdl_remove()) instead of transitioning directly to the
Q921_TEI_UNASSIGNED state. Necessary state clean-up was not
getting done. * Minor tweaks to q921_mdl_remove(). The worst
problem was erroneously generating an error message. * Fixed
potential for sending I-frames with an invalid TEI. The I-frame
could have been queued when Q.921 did not have an assigned TEI. *
Fixed testing of the q931_receive() return value when a UI-frame
is received. (closes issue #17570) Reported by: jcovert Patches:
issue17570_v1.4.11.3_v3.patch uploaded by rmudgett (license 664)
issue17570_v1.4_v3.patch uploaded by rmudgett (license 664)
Tested by: jcovert, rmudgett
2010-08-27 23:37 +0000 [r1894-1912] Richard Mudgett <rmudgett@digium.com>
* pri.c, q931.c: Convert most references of Q931_MAX_TEI to use
ARRAY_LEN(). * Minor comment correction in q931_destroycall(). *
Redundant logic removal q931_destroycall(). "W && X && (Y || W &&
Z)" is the same as "W && X && (Y || Z)"
* rose.c, rosetest.c: Add support to receive ECMA-164 2nd edition
OID name ROSE messages. NOTE: To add support to send the old
style name messages will require implementing them as new ROSE
operation message types. NOTE: To actually use them would likely
require implementing another version of the Q.SIG switch type.
Like (NI1 & NI2) and (4ess & 5ess) for example. Patches:
libpri37.patch uploaded by rmudgett (license 664) JIRA SWP-2100
JIRA LIBPRI-37
* pri.c: Make pri_dump_event() only print the event name.
2010-08-25 17:17 +0000 [r1883-1884] Richard Mudgett <rmudgett@digium.com>
* rosetest.c: Added gripe check to rosetest for invalid operation
and error codes.
* q921.c: Don't silently fail to post our fake MDL-ERROR(Z).
2010-08-23 22:13 +0000 [r1878] Matthew Fredrickson <creslin@digium.com>
* q921.c: Add silly fake MDL error Z for kicking L2 to reactivate
if a DISC or DM is received in proper states on PTP links.
2010-08-06 18:35 +0000 [r1852-1853] Richard Mudgett <rmudgett@digium.com>
* q931.c: No audio on inbound J1 calls. Incoming calls specifying
the channel using a slot map could not negotiate a B channel
correctly. Libpri historically has handled this as an any channel
request. However, when chan_dahdi picked a new channel, libpri
sent out the recorded slot map and not the new channel selected.
Thus the two endpoints would be attached to different B channels
and the parties would not hear anything or would hear the wrong
parties. This patch restores the historical preference of sending
out the channel id using the channel number method if a channel
number is available. JIRA LIBPRI-35 Patches:
libpri-35_v1.4.11.3.patch uploaded by rmudgett (license 664)
libpri-35_v1.4.patch uploaded by rmudgett (license 664) Tested
by: rmudgett
* q921.c: Learn (AGAIN!) why state 7 and state 8 transitions were
suppressed.
2010-08-03 23:04 +0000 [r1842-1848] Richard Mudgett <rmudgett@digium.com>
* q921.c, q931.c: Improved Q.921/Q.931 debug output. * Debug output
for a sent Q.931 message in TE PTMP now uses the best available
TEI number instead of always using 127. It could still be wrong
if layer 2 does not have a TEI assigned. * Q.921 debug output is
grouped better so a decoded message is not split by a blank line.
* The Q.921 state is also decoded to a name.
* q921.c: Q921_TIMER_RECOVERY SDL issue in q921_rnr_rx() Added
missing code specified by Q.921 (Figure B.8 Page 85) when receive
RNR in "Timer Recovery" state. (closes issue #16791) Reported by:
alecdavis Patches: rnr_timer_recovery.diff.txt uploaded by
alecdavis (license 585)
* q921.c: Renamed local struct pri *pri variables to struct pri
*ctrl in q921.c. The context tagging for my editor is much
happier now that the struct and the variable do not have the same
name. (At least for this file.)
2010-07-26 Leif Madsen <lmadsen@digium.com>
* libpri 1.4.12-beta1 released
2010-07-22 17:59 +0000 [r1836] Richard Mudgett <rmudgett@digium.com>
* pri.c, libpri.h: Add pri_new_bri_cb() API - Create BRI D-channel
with user defined I/O callbacks and data There currently exists a
pri_new_cb() API call that allows you to create a PRI with
user-defined I/O read and write callbacks, and option userdata.
Add the same capability for BRI interfaces by adding a
pri_new_bri_cb() API function. (closes issue #16477) Reported by:
nic_bellamy Patches: pri_new_bri_cb_api.patch uploaded by nic
bellamy (license 299) (with minor cosmetic changes)
2010-07-16 22:55 +0000 [r1828-1833] Richard Mudgett <rmudgett@digium.com>
* pritest.c, Makefile: pritest hadn't been ported to DAHDI pritest
hadn't been ported to DAHDI, made the trivial changes to make it
work. (I haven't found the equivalent to zap_playf, so changed
the behaviour to an echo box) (closes issue #17274) Reported by:
horape Patches: pritest.diff uploaded by horape (license 1035)
(with minor cosmetic changes)
* rosetest.c: Only need to output one version of the version
message.
* rosetest.c: Added a libpri version output line as a sanity check
for rosetest.
* rosetest.c, rose_qsig_name.c: Calling name not successfully
processed on inbound QSIG PRI calls from Mitel PBX The alternate
form of the Q.SIG Name sequence that allows manufacturer
extensions for CallingName, CalledName, ConnectedName, and
BusyName was not consuming the next ASN.1 tag. The code that
processed the ASN.1 Name structure was then using a stale tag
value. The stale tag value was then rejected with the "Did not
expect" message. I have added a test case using the supplied PRI
debug output to the rosetest utility to verify that this
alternate encoding is tested in the future. (closes issue #17619)
Reported by: jims8650 Patches: issue17619_v1.4.11.3.patch
uploaded by rmudgett (license 664) Tested by: rmudgett
2010-06-29 16:15 +0000 [r1823] Richard Mudgett <rmudgett@digium.com>
* pri_internal.h, q931.c: [regression] Calling Number assignment
logic change in libpri 1.4.11. Restored the old behaviour if
there is more than one calling number in the incoming SETUP
message. A network provided number is reported as ANI. (closes
issue #17495) Reported by: ibercom Patches:
issue_17495_v1.4.11.2.patch uploaded by rmudgett (license 664)
issue_17495_v1.4.patch uploaded by rmudgett (license 664) Tested
by: ibercom
2010-06-25 20:22 +0000 [r1818] Richard Mudgett <rmudgett@digium.com>
* q931.c: PRI: XXX Missing handling for mandatory IE 12 The switch
is sending the Connected Address ie (12) and there was no handler
for that ie. That is why the reporter was getting the "Missing
mandatory ie" message. The simple fix is to just add the missing
receive handler for that ie. Since connected line (COLP)
functionality has been added and this is just an alternate for
the Connected Number ie (0x4C), the handler was already written.
I also changed the ie name to what Q.931 calls it: Connected
Address. Also some minor code clean up in q931_handle_ie() and
ie2str(). JIRA SWP-1678 (closes issue #16915) Reported by: kobaz
2010-06-04 22:45 +0000 [r1810] Richard Mudgett <rmudgett@digium.com>
* pri_facility.c: Q.SIG calling name in FACILITY message not
reported to the upper layer. Q.SIG can send the CallingName,
CalledName, and ConnectedName in stand alone FACILITY messages.
If the CallingName was not sent in the SETUP message, the caller
id name was not reported to the upper layer. (closes issue
#17458) Reported by: jsmith Patches:
issue17458_post_qsig_name.patch uploaded by rmudgett (license
664) issue17458_post_qsig_name_v1.4.11.1.patch uploaded by
rmudgett (license 664) Tested by: rmudgett, jsmith
2010-06-01 22:59 +0000 [r1785-1794] Richard Mudgett <rmudgett@digium.com>
* pri.c: Inband disconnect setting does nothing on BRI spans. The
acceptinbanddisconnect flag is not inherited when creating a new
TEI and thus rendering the setting (and its respective equivalent
in Asterisk) a no-op on BRI setups. (closes issue #15265)
Reported by: paravoid Patches: inband-bri.diff uploaded by
paravoid (license 200) Tested by: paravoid
* rose.c, rosetest.c, q931.c: Multi component FACILITY messages
only process the first component. The code was only processing
the first ROSE component in the facility message. I also updated
rosetest.c to have a multiple component ROSE message test.
(closes issue #17428) Reported by: patrol-cz Patches:
issue17428.patch uploaded by rmudgett (license 664) Tested by:
rmudgett, patrol-cz
2010-05-28 22:34 +0000 [r1776] David Vossel <dvossel@digium.com>
* pri_internal.h, pri_aoc.c, q931.c, pri_facility.c,
pri_facility.h, libpri.h: support for sending ETSI advice of
charge Review: https://reviewboard.asterisk.org/r/619/
2010-05-28 21:50 +0000 [r1723-1767] Richard Mudgett <rmudgett@digium.com>
* rose_etsi_mwi.c (added), rose.c, rosetest.c, rose_internal.h,
Makefile, rose.h, pri_facility.c, libpri.h, rose_qsig_mwi.c: ETSI
Message Waiting Indication (MWI) support. Add the ability to
report waiting messages to ISDN endpoints (phones). Relevant
specification: EN 300 650 and EN 300 745 Review:
https://reviewboard.asterisk.org/r/600/
* rose.c, rosetest.c, pri_internal.h, rose.h, pri_facility.c,
libpri.h: ETSI Malicious Call ID support. Add the ability to
report malicious callers. Relevant specification: EN 300 180
Review: https://reviewboard.asterisk.org/r/575/
* pri.c, pri_internal.h, pri_q931.h, q931.c, libpri.h: ETSI Call
Waiting support. Add the ability to announce a call to an
endpoint when there are no B channels available. A call waiting
call is a SETUP message with no B channel selected. Relevant
specification: EN 300 056, EN 300 057, EN 300 058 Review:
https://reviewboard.asterisk.org/r/569/
* pri_internal.h, pri_aoc.c (added), Makefile, pri_facility.c,
rose_etsi_aoc.c, pri_facility.h, libpri.h: ETSI Advice Of Charge
(AOC) event reporting. This feature passes ETSI AOC-S, AOC-D, and
AOC-E message information to the upper layer (i.e. Asterisk) for
processing. Relevant specification: EN 300 182 Consideration was
made for the possible future addition of Q.SIG AOC support
(ECMA-212) with the events passed to the upper layer. Review:
https://reviewboard.asterisk.org/r/538/
* pri.c, pri_internal.h, q931.c, pri_facility.c, pri_facility.h,
libpri.h: Added ETSI Explicit Call Transfer (ECT) support. Added
ability to send and receive ETSI ECT messages to eliminate
tromboned calls. Added ETSI support to an existing API call to
send ECT messages when the upper level indicates to transfer
specified calls. The libpri API was extended to indicate to the
upper layer that the far end requests the transfer of the
indicated calls. Review: https://reviewboard.asterisk.org/r/521/
2010-05-26 16:01 +0000 [r1714] Richard Mudgett <rmudgett@digium.com>
* pri.c, doc/cc_ptmp_monitor_flattened.fsm, pri_internal.h,
Makefile, q931.c, doc/cc_ptp_agent.fsm, doc/cc_qsig_agent.fsm,
pri_cc.c (added), rose_qsig_cc.c (added), prisched.c,
doc/cc_ptmp_agent_flattened.fsm, rose_etsi_cc.c (added),
doc/cc_ptmp_monitor.fsm, rosetest.c, rose.c, rose_internal.h,
doc/cc_ptmp_agent.fsm, pri_q931.h,
doc/cc_qsig_monitor_flattened.fsm,
doc/cc_ptp_monitor_flattened.fsm, rose.h, pri_facility.c,
pri_facility.h, doc/cc_qsig_agent_flattened.fsm,
doc/cc_ptp_agent_flattened.fsm, doc (added), libpri.h,
doc/cc_qsig_monitor.fsm, doc/cc_ptp_monitor.fsm: Add Call
Completion Suppplementary Service Call Completion Supplementary
Service (CCSS) added for the following switch types: ETSI PTMP,
ETSI PTP, Q.SIG. Specifications: ETS 300 359 CCBS for PTMP and
PTP ETS 301 065 CCNR for PTMP and PTP ECMA-186 Call Completion
for Q.SIG Several support services were added to support CC:
Dummy Call Reference. Q.931 REGISTER message. Dynamic expansion
of the number of available timers (up to 8192). Enhanced facility
message handling. Current implementation limitations preclude the
following: CC service retention is not supported. Q.SIG path
reservation is not supported. (closes issue #14292) Reported by:
tomaso Tested by: rmudgett JIRA SWP-1493 Review:
https://reviewboard.asterisk.org/r/522/
2010-06-29 Leif Madsen <lmadsen@digium.com>
* libpri 1.4.11.3 released.
2010-06-29 11:17 +0000 [r1824] Richard Mudgett <rmudgett@digium.com>
* pri_internal.h, q931.c: [regression] Calling Number assignment
logic change in libpri 1.4.11. Restored the old behaviour if
there is more than one calling number in the incoming SETUP
message. A network provided number is reported as ANI. (closes
issue #17495) Reported by: ibercom Patches:
issue_17495_v1.4.11.2.patch uploaded by rmudgett (license 664)
issue_17495_v1.4.patch uploaded by rmudgett (license 664) Tested
by: ibercom
2010-06-02 Leif Madsen <lmadsen@digium.com>
* libpri 1.4.11.2 released.
2010-06-04 17:45 +0000 [r1810] Richard Mudgett <rmudgett@digium.com>
* pri_facility.c: Q.SIG calling name in FACILITY message not
reported to the upper layer. Q.SIG can send the CallingName,
CalledName, and ConnectedName in stand alone FACILITY messages.
If the CallingName was not sent in the SETUP message, the caller
id name was not reported to the upper layer. (closes issue #17458)
Reported by: jsmith Patches: issue17458_post_qsig_name.patch uploaded
by rmudgett (license 664) issue17458_post_qsig_name_v1.4.11.1.patch
uploaded by rmudgett (license 664) Tested by: rmudgett, jsmith
2010-06-02 Leif Madsen <lmadsen@digium.com>
* libpri 1.4.11.1 released.
2010-06-02 11:26 +0000 [r1805-1806] Richard Mudgett <rmudgett@digium.com>
* pri.c: Inband disconnect setting does nothing on BRI spans.
The acceptinbanddisconnect flag is not inherited when creating
a new TEI and thus rendering the setting (and its respective
equivalent in Asterisk) a no-op on BRI setups. (closes issue
#15265) Reported by: paravoid Patches: inband-bri.diff uploaded
by paravoid (license 200) Tested by: paravoid
* q931.c, rose.c, rosetest.c: Multi component FACILITY messages
only process the first component. The code was only processing
the first ROSE component in the facility message. I also updated
rosetest.c to have a multiple component ROSE message test.
(closes issue #17428) Reported by: patrol-cz Patches:
issue17428.patch uploaded by rmudgett (license 664) Tested by:
rmudgett, patrol-cz
2010-05-20 Russell Bryant <russell@digium.com>
* libpri 1.4.11 released.

View File

@@ -47,16 +47,21 @@ STATIC_OBJS= \
q921.o \
prisched.o \
q931.o \
pri_aoc.o \
pri_cc.o \
pri_facility.o \
asn1_primitive.o \
rose.o \
rose_address.o \
rose_etsi_aoc.o \
rose_etsi_cc.o \
rose_etsi_diversion.o \
rose_etsi_ect.o \
rose_etsi_mwi.o \
rose_other.o \
rose_q931.o \
rose_qsig_aoc.o \
rose_qsig_cc.o \
rose_qsig_ct.o \
rose_qsig_diversion.o \
rose_qsig_mwi.o \
@@ -68,16 +73,21 @@ DYNAMIC_OBJS= \
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 \
@@ -168,7 +178,7 @@ uninstall:
rm -f $(INSTALL_PREFIX)$(INSTALL_BASE)/include/libpri.h
pritest: pritest.o
$(CC) -o pritest pritest.o -L. -lpri -lzap $(CFLAGS)
$(CC) -o pritest pritest.o -L. -lpri $(CFLAGS)
testprilib.o: testprilib.c
$(CC) $(CFLAGS) -D_REENTRANT -D_GNU_SOURCE -o $@ -c $<

366
doc/cc_ptmp_agent.fsm Normal file
View File

@@ -0,0 +1,366 @@
/*
* FSM pseudo code used in the design/implementation of the CC PTMP agent.
*/
FSM CC_PTMP_Agent
{
State CC_STATE_IDLE {
Init {
}
Prolog {
Action Set_Selfdestruct;
}
Stimulus CC_EVENT_AVAILABLE {
Next_State CC_STATE_PENDING_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
}
}
State CC_STATE_PENDING_AVAILABLE {
Stimulus CC_EVENT_MSG_ALERTING {
Action Send_CC_Available(Q931_ALERTING);
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_MSG_DISCONNECT {
Action Send_CC_Available(Q931_DISCONNECT);
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_AVAILABLE {
Epilog {
Action Stop_T_RETENTION;
}
Stimulus CC_EVENT_MSG_RELEASE {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_MSG_RELEASE_COMPLETE {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_CC_REQUEST {
Action Pass_Up_CC_Request;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_TIMEOUT_T_RETENTION {
Action Send_EraseCallLinkageID;
Action Relese_LinkID;
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Send_EraseCallLinkageID;
Action Relese_LinkID;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_REQUESTED {
Epilog {
Action Send_EraseCallLinkageID;
Action Relese_LinkID;
}
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_CANCEL {
Next_State CC_STATE_IDLE;
}
}
/*
* Pass_Up_A_Status passes up the current final status of A.
* Does nothing if status is invalid.
*
* Pass_Up_A_Status_Indirect is the same as Pass_Up_A_Status but
* sets a timer to expire immediately to pass up the event.
* Does nothing if status is invalid.
*
* Pass_Up_Status_Rsp_A passes up the current accumulated status of A.
* Does nothing if status is invalid.
*
* Pass_Up_Status_Rsp_A_Indirect is the same as Pass_Up_Status_Rsp_A but
* sets a timer to expire immediately to pass up the event.
* Does nothing if status is invalid.
*/
State CC_STATE_ACTIVATED {
Prolog {
Action Reset_A_Status;
Action Raw_Status_Count_Reset;
}
Stimulus CC_EVENT_RECALL {
Action Send_Error_Recall(ROSE_ERROR_CCBS_NotReadyForCall);
Action Set_Call_To_Hangup;
}
Stimulus CC_EVENT_B_FREE {
Action Send_CCBSBFree;
}
Stimulus CC_EVENT_REMOTE_USER_FREE {
Test = Get_A_Status;
Test == Invalid {
Next_State CC_STATE_B_AVAILABLE;
}
Test == Busy {
Action Pass_Up_A_Status_Indirect;
Action Send_CCBSBFree;
Next_State CC_STATE_SUSPENDED;
}
Test == Free {
//Action Pass_Up_A_Status_Indirect;
Action Send_RemoteUserFree;
Next_State CC_STATE_WAIT_CALLBACK;
}
}
Stimulus CC_EVENT_A_STATUS {
Test = Get_T_CCBS1_Status;
Test == Active {
Action Pass_Up_Status_Rsp_A_Indirect;
Next_State $;
}
Test != Active {
Action Reset_A_Status;
Action Reset_Raw_A_Status;
Action Send_CCBSStatusRequest;
Action Start_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Start_Extended_T_CCBS1;
Next_State $;
}
}
Stimulus CC_EVENT_A_FREE {
Action Raw_Status_Count_Reset;
Action Set_Raw_A_Status_Free;
Action Promote_Raw_A_Status;
Action Pass_Up_Status_Rsp_A;
Action Stop_T_CCBS1;
}
Stimulus CC_EVENT_A_BUSY {
Action Add_Raw_A_Status_Busy;
Action Pass_Up_Status_Rsp_A;
}
Stimulus CC_EVENT_TIMEOUT_T_CCBS1 {
Action Promote_Raw_A_Status;
Test = Get_A_Status;
Test != Invalid {
/* Only received User A busy. */
Action Raw_Status_Count_Reset;
}
Test == Invalid {
/* Did not get any responses. */
Action Raw_Status_Count_Increment;
Test = Get_Raw_Status_Count;
Test >= RAW_STATUS_COUNT_MAX {
/* User A no longer present. */
Action Send_CCBSErase(Normal_Unspecified);
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
}
}
Stimulus CC_EVENT_TIMEOUT_EXTENDED_T_CCBS1 {
Action Reset_A_Status;
Action Raw_Status_Count_Reset;
}
}
State CC_STATE_B_AVAILABLE {
/* A status is always invalid on entry. */
Prolog {
Test = Get_T_CCBS1_Status;
Test != Active {
Action Reset_Raw_A_Status;
Action Send_CCBSStatusRequest;
Action Start_T_CCBS1;
}
}
Stimulus CC_EVENT_RECALL {
Action Send_Error_Recall(ROSE_ERROR_CCBS_NotReadyForCall);
Action Set_Call_To_Hangup;
}
Stimulus CC_EVENT_A_STATUS {
Action Stop_Extended_T_CCBS1;
Action Start_Extended_T_CCBS1;
Action Pass_Up_Status_Rsp_A_Indirect;
}
Stimulus CC_EVENT_A_FREE {
Action Send_RemoteUserFree;
Action Set_Raw_A_Status_Free;
//Action Promote_Raw_A_Status;
//Action Pass_Up_A_Status;
Test = Get_Extended_T_CCBS1_Status;
Test == Active {
Action Pass_Up_Status_Rsp_A;
}
Next_State CC_STATE_WAIT_CALLBACK;
}
Stimulus CC_EVENT_A_BUSY {
Action Add_Raw_A_Status_Busy;
Test = Get_Extended_T_CCBS1_Status;
Test == Active {
Action Pass_Up_Status_Rsp_A;
}
}
Stimulus CC_EVENT_TIMEOUT_T_CCBS1 {
Test = Get_Raw_A_Status;
Test != Invalid {
/* Only received User A is busy. */
Action Raw_Status_Count_Reset;
Action Send_CCBSBFree;
Action Promote_Raw_A_Status;
Action Pass_Up_A_Status;
Next_State CC_STATE_SUSPENDED;
}
Test == Invalid {
/* Did not get any responses. */
Action Raw_Status_Count_Increment;
Test = Get_Raw_Status_Count;
Test >= RAW_STATUS_COUNT_MAX {
/* User A no longer present. */
Action Send_CCBSErase(Normal_Unspecified);
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
//Action Reset_Raw_A_Status;
Action Send_CCBSStatusRequest;
Action Start_T_CCBS1;
}
}
}
State CC_STATE_SUSPENDED {
Prolog {
Test = Get_T_CCBS1_Status;
Test != Active {
Action Reset_Raw_A_Status;
Action Send_CCBSStatusRequest;
Action Start_T_CCBS1;
}
}
Stimulus CC_EVENT_RECALL {
Action Send_Error_Recall(ROSE_ERROR_CCBS_NotReadyForCall);
Action Set_Call_To_Hangup;
}
Stimulus CC_EVENT_A_STATUS {
Action Stop_Extended_T_CCBS1;
Action Start_Extended_T_CCBS1;
Action Pass_Up_Status_Rsp_A_Indirect;
}
Stimulus CC_EVENT_A_FREE {
Action Set_Raw_A_Status_Free;
Action Promote_Raw_A_Status;
Action Pass_Up_A_Status;
Test = Get_Extended_T_CCBS1_Status;
Test == Active {
Action Pass_Up_Status_Rsp_A;
}
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_A_BUSY {
Action Add_Raw_A_Status_Busy;
Test = Get_Extended_T_CCBS1_Status;
Test == Active {
Action Pass_Up_Status_Rsp_A;
}
}
Stimulus CC_EVENT_TIMEOUT_T_CCBS1 {
Test = Get_Raw_A_Status;
Test != Invalid {
/* Only received User A is busy. */
Action Raw_Status_Count_Reset;
}
Test == Invalid {
/* Did not get any responses. */
Action Raw_Status_Count_Increment;
Test = Get_Raw_Status_Count;
Test >= RAW_STATUS_COUNT_MAX {
/* User A no longer present. */
Action Send_CCBSErase(Normal_Unspecified);
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
}
Action Reset_Raw_A_Status;
Action Send_CCBSStatusRequest;
Action Start_T_CCBS1;
}
}
State CC_STATE_WAIT_CALLBACK {
Prolog {
/* Start T_CCBS3 */
Action Start_T_RECALL;
}
Epilog {
Action Stop_T_RECALL;
}
Stimulus CC_EVENT_TIMEOUT_T_RECALL {
Action Pass_Up_CC_Cancel;
Action Send_CCBSErase(T_CCBS3_TIMEOUT);
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_STOP_ALERTING {
/*
* If an earlier link can send us this event then we
* really should be configured for globalRecall like
* the earlier link.
*/
Test = Get_Recall_Mode;
Test == globalRecall {
Action Send_CCBSStopAlerting;
}
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_RECALL {
Action Pass_Up_CC_Call;
Action Set_Original_Call_Parameters;
Test = Get_Recall_Mode;
Test == globalRecall {
Action Send_CCBSStopAlerting;
}
Next_State CC_STATE_CALLBACK;
}
Stimulus CC_EVENT_A_STATUS {
Action Set_Raw_A_Status_Free;
Action Pass_Up_Status_Rsp_A_Indirect;
}
}
State CC_STATE_CALLBACK {
Stimulus CC_EVENT_RECALL {
Action Send_Error_Recall(ROSE_ERROR_CCBS_AlreadyAccepted);
Action Set_Call_To_Hangup;
}
Stimulus CC_EVENT_A_STATUS {
Action Set_Raw_A_Status_Free;
Action Pass_Up_Status_Rsp_A_Indirect;
}
}
Superstate CC_ACTIVE(CC_STATE_ACTIVATED, CC_STATE_B_AVAILABLE, CC_STATE_SUSPENDED, CC_STATE_WAIT_CALLBACK, CC_STATE_CALLBACK) {
Prolog {
/* Start T_CCBS2 or T_CCNR2 depending upon CC mode. */
Action Start_T_SUPERVISION;
}
Epilog {
Action Stop_T_SUPERVISION;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CCBSErase(T_CCBS2_TIMEOUT);
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_LINK_CANCEL {
Action Pass_Up_CC_Cancel;
Action Send_CCBSErase(Normal_Unspecified);
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CCBSErase(Normal_Unspecified);
Next_State CC_STATE_IDLE;
}
}
Superstate CC_STATUS(CC_STATE_ACTIVATED, CC_STATE_B_AVAILABLE, CC_STATE_SUSPENDED) {
Epilog {
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
}
}
}

View File

@@ -0,0 +1,483 @@
/*
* FSM pseudo code used in the design/implementation of the CC PTMP agent.
*/
FSM CC_PTMP_Agent
{
State CC_STATE_IDLE {
Stimulus CC_EVENT_AVAILABLE {
Next_State CC_STATE_PENDING_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
}
}
State CC_STATE_PENDING_AVAILABLE {
Stimulus CC_EVENT_MSG_ALERTING {
Action Send_CC_Available(Q931_ALERTING);
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_MSG_DISCONNECT {
Action Send_CC_Available(Q931_DISCONNECT);
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_AVAILABLE {
Stimulus CC_EVENT_MSG_RELEASE {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_MSG_RELEASE_COMPLETE {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_CC_REQUEST {
Action Pass_Up_CC_Request;
Action Stop_T_RETENTION;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_TIMEOUT_T_RETENTION {
Action Send_EraseCallLinkageID;
Action Relese_LinkID;
Action Pass_Up_CC_Cancel;
Action Stop_T_RETENTION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Send_EraseCallLinkageID;
Action Relese_LinkID;
Action Stop_T_RETENTION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_REQUESTED {
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
Action Send_EraseCallLinkageID;
Action Relese_LinkID;
/* Start T_CCBS2 or T_CCNR2 depending upon CC mode. */
Action Start_T_SUPERVISION;
Action Reset_A_Status;
Action Raw_Status_Count_Reset;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_CANCEL {
Action Send_EraseCallLinkageID;
Action Relese_LinkID;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
/*
* Pass_Up_A_Status passes up the current final status of A.
* Does nothing if status is invalid.
*
* Pass_Up_A_Status_Indirect is the same as Pass_Up_A_Status but
* sets a timer to expire immediately to pass up the event.
* Does nothing if status is invalid.
*
* Pass_Up_Status_Rsp_A passes up the current accumulated status of A.
* Does nothing if status is invalid.
*
* Pass_Up_Status_Rsp_A_Indirect is the same as Pass_Up_Status_Rsp_A but
* sets a timer to expire immediately to pass up the event.
* Does nothing if status is invalid.
*/
State CC_STATE_ACTIVATED {
Stimulus CC_EVENT_RECALL {
Action Send_Error_Recall(ROSE_ERROR_CCBS_NotReadyForCall);
Action Set_Call_To_Hangup;
}
Stimulus CC_EVENT_B_FREE {
Action Send_CCBSBFree;
}
Stimulus CC_EVENT_REMOTE_USER_FREE {
Test = Get_A_Status;
Test == Invalid {
Test = Get_T_CCBS1_Status;
Test != Active {
Action Reset_Raw_A_Status;
Action Send_CCBSStatusRequest;
Action Start_T_CCBS1;
}
Next_State CC_STATE_B_AVAILABLE;
}
Test == Busy {
Action Pass_Up_A_Status_Indirect;
Action Send_CCBSBFree;
Test = Get_T_CCBS1_Status;
Test != Active {
Action Reset_Raw_A_Status;
Action Send_CCBSStatusRequest;
Action Start_T_CCBS1;
}
Next_State CC_STATE_SUSPENDED;
}
Test == Free {
//Action Pass_Up_A_Status_Indirect;
Action Send_RemoteUserFree;
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
/* Start T_CCBS3 */
Action Start_T_RECALL;
Next_State CC_STATE_WAIT_CALLBACK;
}
}
Stimulus CC_EVENT_A_STATUS {
Test = Get_T_CCBS1_Status;
Test == Active {
Action Pass_Up_Status_Rsp_A_Indirect;
Next_State $;
}
Test != Active {
Action Reset_A_Status;
Action Reset_Raw_A_Status;
Action Send_CCBSStatusRequest;
Action Start_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Start_Extended_T_CCBS1;
Next_State $;
}
}
Stimulus CC_EVENT_A_FREE {
Action Raw_Status_Count_Reset;
Action Set_Raw_A_Status_Free;
Action Promote_Raw_A_Status;
Action Pass_Up_Status_Rsp_A;
Action Stop_T_CCBS1;
}
Stimulus CC_EVENT_A_BUSY {
Action Add_Raw_A_Status_Busy;
Action Pass_Up_Status_Rsp_A;
}
Stimulus CC_EVENT_TIMEOUT_T_CCBS1 {
Action Promote_Raw_A_Status;
Test = Get_A_Status;
Test != Invalid {
/* Only received User A busy. */
Action Raw_Status_Count_Reset;
}
Test == Invalid {
/* Did not get any responses. */
Action Raw_Status_Count_Increment;
Test = Get_Raw_Status_Count;
Test >= RAW_STATUS_COUNT_MAX {
/* User A no longer present. */
Action Send_CCBSErase(Normal_Unspecified);
Action Pass_Up_CC_Cancel;
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
}
Stimulus CC_EVENT_TIMEOUT_EXTENDED_T_CCBS1 {
Action Reset_A_Status;
Action Raw_Status_Count_Reset;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CCBSErase(T_CCBS2_TIMEOUT);
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_LINK_CANCEL {
Action Pass_Up_CC_Cancel;
Action Send_CCBSErase(Normal_Unspecified);
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CCBSErase(Normal_Unspecified);
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_B_AVAILABLE {
/* A status is always invalid on entry. */
Stimulus CC_EVENT_RECALL {
Action Send_Error_Recall(ROSE_ERROR_CCBS_NotReadyForCall);
Action Set_Call_To_Hangup;
}
Stimulus CC_EVENT_A_STATUS {
Action Stop_Extended_T_CCBS1;
Action Start_Extended_T_CCBS1;
Action Pass_Up_Status_Rsp_A_Indirect;
}
Stimulus CC_EVENT_A_FREE {
Action Send_RemoteUserFree;
Action Set_Raw_A_Status_Free;
//Action Promote_Raw_A_Status;
//Action Pass_Up_A_Status;
Test = Get_Extended_T_CCBS1_Status;
Test == Active {
Action Pass_Up_Status_Rsp_A;
}
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
/* Start T_CCBS3 */
Action Start_T_RECALL;
Next_State CC_STATE_WAIT_CALLBACK;
}
Stimulus CC_EVENT_A_BUSY {
Action Add_Raw_A_Status_Busy;
Test = Get_Extended_T_CCBS1_Status;
Test == Active {
Action Pass_Up_Status_Rsp_A;
}
}
Stimulus CC_EVENT_TIMEOUT_T_CCBS1 {
Test = Get_Raw_A_Status;
Test != Invalid {
/* Only received User A is busy. */
Action Raw_Status_Count_Reset;
Action Send_CCBSBFree;
Action Promote_Raw_A_Status;
Action Pass_Up_A_Status;
/* Optimization due to flattening */
//Test = Get_T_CCBS1_Status;
//Test != Active
{
Action Reset_Raw_A_Status;
Action Send_CCBSStatusRequest;
Action Start_T_CCBS1;
}
Next_State CC_STATE_SUSPENDED;
}
Test == Invalid {
/* Did not get any responses. */
Action Raw_Status_Count_Increment;
Test = Get_Raw_Status_Count;
Test >= RAW_STATUS_COUNT_MAX {
/* User A no longer present. */
Action Send_CCBSErase(Normal_Unspecified);
Action Pass_Up_CC_Cancel;
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
//Action Reset_Raw_A_Status;
Action Send_CCBSStatusRequest;
Action Start_T_CCBS1;
}
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CCBSErase(T_CCBS2_TIMEOUT);
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_LINK_CANCEL {
Action Pass_Up_CC_Cancel;
Action Send_CCBSErase(Normal_Unspecified);
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CCBSErase(Normal_Unspecified);
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_SUSPENDED {
Stimulus CC_EVENT_RECALL {
Action Send_Error_Recall(ROSE_ERROR_CCBS_NotReadyForCall);
Action Set_Call_To_Hangup;
}
Stimulus CC_EVENT_A_STATUS {
Action Stop_Extended_T_CCBS1;
Action Start_Extended_T_CCBS1;
Action Pass_Up_Status_Rsp_A_Indirect;
}
Stimulus CC_EVENT_A_FREE {
Action Set_Raw_A_Status_Free;
Action Promote_Raw_A_Status;
Action Pass_Up_A_Status;
Test = Get_Extended_T_CCBS1_Status;
Test == Active {
Action Pass_Up_Status_Rsp_A;
}
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Reset_A_Status;
Action Raw_Status_Count_Reset;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_A_BUSY {
Action Add_Raw_A_Status_Busy;
Test = Get_Extended_T_CCBS1_Status;
Test == Active {
Action Pass_Up_Status_Rsp_A;
}
}
Stimulus CC_EVENT_TIMEOUT_T_CCBS1 {
Test = Get_Raw_A_Status;
Test != Invalid {
/* Only received User A is busy. */
Action Raw_Status_Count_Reset;
}
Test == Invalid {
/* Did not get any responses. */
Action Raw_Status_Count_Increment;
Test = Get_Raw_Status_Count;
Test >= RAW_STATUS_COUNT_MAX {
/* User A no longer present. */
Action Send_CCBSErase(Normal_Unspecified);
Action Pass_Up_CC_Cancel;
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
Action Reset_Raw_A_Status;
Action Send_CCBSStatusRequest;
Action Start_T_CCBS1;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CCBSErase(T_CCBS2_TIMEOUT);
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_LINK_CANCEL {
Action Pass_Up_CC_Cancel;
Action Send_CCBSErase(Normal_Unspecified);
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CCBSErase(Normal_Unspecified);
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_WAIT_CALLBACK {
Stimulus CC_EVENT_TIMEOUT_T_RECALL {
Action Pass_Up_CC_Cancel;
Action Send_CCBSErase(T_CCBS3_TIMEOUT);
Action Stop_T_RECALL;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_STOP_ALERTING {
/*
* If an earlier link can send us this event then we
* really should be configured for globalRecall like
* the earlier link.
*/
Test = Get_Recall_Mode;
Test == globalRecall {
Action Send_CCBSStopAlerting;
}
Action Stop_T_RECALL;
Action Reset_A_Status;
Action Raw_Status_Count_Reset;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_RECALL {
Action Pass_Up_CC_Call;
Action Set_Original_Call_Parameters;
Test = Get_Recall_Mode;
Test == globalRecall {
Action Send_CCBSStopAlerting;
}
Action Stop_T_RECALL;
Next_State CC_STATE_CALLBACK;
}
Stimulus CC_EVENT_A_STATUS {
Action Set_Raw_A_Status_Free;
Action Pass_Up_Status_Rsp_A_Indirect;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CCBSErase(T_CCBS2_TIMEOUT);
Action Stop_T_RECALL;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_LINK_CANCEL {
Action Pass_Up_CC_Cancel;
Action Send_CCBSErase(Normal_Unspecified);
Action Stop_T_RECALL;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CCBSErase(Normal_Unspecified);
Action Stop_T_RECALL;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_CALLBACK {
Stimulus CC_EVENT_RECALL {
Action Send_Error_Recall(ROSE_ERROR_CCBS_AlreadyAccepted);
Action Set_Call_To_Hangup;
}
Stimulus CC_EVENT_A_STATUS {
Action Set_Raw_A_Status_Free;
Action Pass_Up_Status_Rsp_A_Indirect;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CCBSErase(T_CCBS2_TIMEOUT);
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_LINK_CANCEL {
Action Pass_Up_CC_Cancel;
Action Send_CCBSErase(Normal_Unspecified);
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CCBSErase(Normal_Unspecified);
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
}

181
doc/cc_ptmp_monitor.fsm Normal file
View File

@@ -0,0 +1,181 @@
/*
* FSM pseudo code used in the design/implementation of the CC PTMP monitor.
*
* The CCBSStatusRequest messages are handled independently from this FSM.
*
* The CCBSInterrogate/CCNRInterrogate messages are initiated by a dialplan
* application/AMI/CLI (future) and are handled outside of this FSM.
*/
FSM CC_PTMP_Monitor
{
State CC_STATE_IDLE {
Init {
}
Prolog {
Action Set_Selfdestruct;
}
Stimulus CC_EVENT_AVAILABLE {
/*
* Before event is posted:
* Received CallInfoRetain
* Created cc_record
* Saved CallLinkageID
*/
Action Pass_Up_CC_Available;
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
}
}
State CC_STATE_AVAILABLE {
/*
* The upper layer is responsible for canceling the CC available
* offering as a safeguard in case the network cable is disconnected.
* The timer should be set much longer than the network T_RETENTION
* timer so normally the CC records will be cleaned up by network
* activity.
*/
Stimulus CC_EVENT_CC_REQUEST {
/* cc_record->is_ccnr is set before event posted. */
Action Queue_CC_Request;
Action Start_T_ACTIVATE;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_TIMEOUT_T_RETENTION {
/*
* Received EraseCallLinkageID
* T_RETENTION expired on the network side so we will pretend
* that it expired on our side.
*/
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_REQUESTED {
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
/*
* Before event is posted:
* Received CCBSRequest/CCNRRequest response
* Saved CCBSReference
*/
Action Relese_LinkID;
Action Pass_Up_CC_Req_Rsp_Success;
Action Stop_T_ACTIVATE;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_CC_REQUEST_FAIL {
Action Pass_Up_CC_Req_Rsp_Fail(error/reject, code);
Action Pass_Up_CC_Cancel;
Action Stop_T_ACTIVATE;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_TIMEOUT_T_ACTIVATE {
Action Pass_Up_CC_Req_Rsp_Timeout;
Action Pass_Up_CC_Cancel;
Action Stop_T_ACTIVATE;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received CCBSErase */
/* Claim it was a timeout */
Action Pass_Up_CC_Req_Rsp_Timeout;
Action Pass_Up_CC_Cancel;
Action Stop_T_ACTIVATE;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Next_State CC_STATE_WAIT_DESTRUCTION;
}
}
State CC_STATE_WAIT_DESTRUCTION {
/* We were in the middle of a cc-request when we were asked to cancel. */
Epilog {
Action Stop_T_ACTIVATE;
}
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
/*
* Before event is posted:
* Received CCBSRequest/CCNRRequest response
* Saved CCBSReference
*/
Action Send_CC_Deactivate_Req;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CC_REQUEST_FAIL {
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_TIMEOUT_T_ACTIVATE {
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received CCBSErase */
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_ACTIVATED {
Stimulus CC_EVENT_B_FREE {
/* Received CCBSBFree */
Action Pass_Up_B_Free;
}
Stimulus CC_EVENT_REMOTE_USER_FREE {
/* Received CCBSRemoteUserFree */
Action Pass_Up_Remote_User_Free;
Next_State CC_STATE_WAIT_CALLBACK;
}
}
State CC_STATE_WAIT_CALLBACK {
Stimulus CC_EVENT_STOP_ALERTING {
Action Pass_Up_Stop_Alerting;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_RECALL {
/* The original call parameters have already been set. */
Action Queue_SETUP_Recall;
Next_State CC_STATE_CALLBACK;
}
}
State CC_STATE_CALLBACK {
/*
* We are waiting for the CC records to be torn down because
* CC is complete.
* This state is mainly to block CC_EVENT_STOP_ALERTING since
* we are the one doing the CC recall so we do not need to stop
* alerting.
*/
}
Superstate CC_ACTIVE(CC_STATE_ACTIVATED, CC_STATE_WAIT_CALLBACK, CC_STATE_CALLBACK) {
Prolog {
/*
* Start T_CCBS2 or T_CCNR2 depending upon CC mode.
* For PTMP TE mode these timers are not defined. However,
* we will use them anyway to protect our resources from leaks
* caused by the network cable being disconnected. These
* timers should be set much longer than the network
* so normally the CC records will be cleaned up by network
* activity.
*/
Action Start_T_SUPERVISION;
}
Epilog {
Action Stop_T_SUPERVISION;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Send_CC_Deactivate_Req;
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received CCBSErase */
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CC_Deactivate_Req;
Next_State CC_STATE_IDLE;
}
}
}

View File

@@ -0,0 +1,225 @@
/*
* FSM pseudo code used in the design/implementation of the CC PTMP monitor.
*
* The CCBSStatusRequest messages are handled independently from this FSM.
*
* The CCBSInterrogate/CCNRInterrogate messages are initiated by a dialplan
* application/AMI/CLI (future) and are handled outside of this FSM.
*/
FSM CC_PTMP_Monitor
{
State CC_STATE_IDLE {
Stimulus CC_EVENT_AVAILABLE {
/*
* Before event is posted:
* Received CallInfoRetain
* Created cc_record
* Saved CallLinkageID
*/
Action Pass_Up_CC_Available;
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
}
}
State CC_STATE_AVAILABLE {
/*
* The upper layer is responsible for canceling the CC available
* offering as a safeguard in case the network cable is disconnected.
* The timer should be set much longer than the network T_RETENTION
* timer so normally the CC records will be cleaned up by network
* activity.
*/
Stimulus CC_EVENT_CC_REQUEST {
/* cc_record->is_ccnr is set before event posted. */
Action Queue_CC_Request;
Action Start_T_ACTIVATE;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_TIMEOUT_T_RETENTION {
/*
* Received EraseCallLinkageID
* T_RETENTION expired on the network side so we will pretend
* that it expired on our side.
*/
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;
}
}
State CC_STATE_REQUESTED {
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
/*
* Before event is posted:
* Received CCBSRequest/CCNRRequest response
* Saved CCBSReference
*/
Action Relese_LinkID;
Action Pass_Up_CC_Req_Rsp_Success;
Action Stop_T_ACTIVATE;
/*
* Start T_CCBS2 or T_CCNR2 depending upon CC mode.
* For PTMP TE mode these timers are not defined. However,
* we will use them anyway to protect our resources from leaks
* caused by the network cable being disconnected. These
* timers should be set much longer than the network
* so normally the CC records will be cleaned up by network
* activity.
*/
Action Start_T_SUPERVISION;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_CC_REQUEST_FAIL {
Action Pass_Up_CC_Req_Rsp_Fail(error/reject, code);
Action Pass_Up_CC_Cancel;
Action Stop_T_ACTIVATE;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_TIMEOUT_T_ACTIVATE {
Action Pass_Up_CC_Req_Rsp_Timeout;
Action Pass_Up_CC_Cancel;
Action Stop_T_ACTIVATE;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received CCBSErase */
/* Claim it was a timeout */
Action Pass_Up_CC_Req_Rsp_Timeout;
Action Pass_Up_CC_Cancel;
Action Stop_T_ACTIVATE;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Next_State CC_STATE_WAIT_DESTRUCTION;
}
}
State CC_STATE_WAIT_DESTRUCTION {
/* We were in the middle of a cc-request when we were asked to cancel. */
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
/*
* Before event is posted:
* Received CCBSRequest/CCNRRequest response
* Saved CCBSReference
*/
Action Send_CC_Deactivate_Req;
Action Stop_T_ACTIVATE;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CC_REQUEST_FAIL {
Action Stop_T_ACTIVATE;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_TIMEOUT_T_ACTIVATE {
Action Stop_T_ACTIVATE;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received CCBSErase */
Action Stop_T_ACTIVATE;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_ACTIVATED {
Stimulus CC_EVENT_B_FREE {
/* Received CCBSBFree */
Action Pass_Up_B_Free;
}
Stimulus CC_EVENT_REMOTE_USER_FREE {
/* Received CCBSRemoteUserFree */
Action Pass_Up_Remote_User_Free;
Next_State CC_STATE_WAIT_CALLBACK;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Send_CC_Deactivate_Req;
Action Pass_Up_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received CCBSErase */
Action Pass_Up_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CC_Deactivate_Req;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_WAIT_CALLBACK {
Stimulus CC_EVENT_STOP_ALERTING {
Action Pass_Up_Stop_Alerting;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_RECALL {
/* The original call parameters have already been set. */
Action Queue_SETUP_Recall;
Next_State CC_STATE_CALLBACK;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Send_CC_Deactivate_Req;
Action Pass_Up_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received CCBSErase */
Action Pass_Up_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CC_Deactivate_Req;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_CALLBACK {
/*
* We are waiting for the CC records to be torn down because
* CC is complete.
* This state is mainly to block CC_EVENT_STOP_ALERTING since
* we are the one doing the CC recall so we do not need to stop
* alerting.
*/
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Send_CC_Deactivate_Req;
Action Pass_Up_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received CCBSErase */
Action Pass_Up_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CC_Deactivate_Req;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
}

144
doc/cc_ptp_agent.fsm Normal file
View File

@@ -0,0 +1,144 @@
/*
* FSM pseudo code used in the design/implementation of the CC PTP agent.
*/
FSM CC_PTP_Agent
{
State CC_STATE_IDLE {
Init {
}
Prolog {
Action Set_Selfdestruct;
}
Stimulus CC_EVENT_AVAILABLE {
Next_State CC_STATE_PENDING_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
}
}
State CC_STATE_PENDING_AVAILABLE {
Stimulus CC_EVENT_MSG_ALERTING {
Action Send_CC_Available(Q931_ALERTING);
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_MSG_DISCONNECT {
Action Send_CC_Available(Q931_DISCONNECT);
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_AVAILABLE {
/*
* For PTP mode the T_RETENTION timer is not defined. However,
* we will use it anyway in this state to protect our resources
* from leaks caused by user A not requesting CC. This timer
* should be set much longer than the PTMP network link to
* allow for variations in user A's CC offer timer.
*/
Epilog {
Action Stop_T_RETENTION;
}
Stimulus CC_EVENT_MSG_RELEASE {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_MSG_RELEASE_COMPLETE {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_CC_REQUEST {
Action Pass_Up_CC_Request;
Action Stop_T_RETENTION;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_TIMEOUT_T_RETENTION {
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_REQUESTED {
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_ACTIVATED {
Prolog {
Action Reset_A_Status;
}
Stimulus CC_EVENT_REMOTE_USER_FREE {
Action Pass_Up_A_Status_Indirect;
Test = Get_A_Status;
Test == Busy {
Next_State CC_STATE_SUSPENDED;
}
Action Send_RemoteUserFree;
Next_State CC_STATE_WAIT_CALLBACK;
}
Stimulus CC_EVENT_SUSPEND {
/* Received CCBS_T_Suspend */
Action Set_A_Status_Busy;
}
Stimulus CC_EVENT_RESUME {
/* Received CCBS_T_Resume */
Action Reset_A_Status;
}
}
State CC_STATE_WAIT_CALLBACK {
Stimulus CC_EVENT_SUSPEND {
/* Received CCBS_T_Suspend */
Action Set_A_Status_Busy;
Action Pass_Up_A_Status;
Next_State CC_STATE_SUSPENDED;
}
}
State CC_STATE_SUSPENDED {
Stimulus CC_EVENT_RESUME {
/* Received CCBS_T_Resume */
Action Set_A_Status_Free;
Action Pass_Up_A_Status;
Next_State CC_STATE_ACTIVATED;
}
}
Superstate CC_ACTIVE(CC_STATE_ACTIVATED, CC_STATE_WAIT_CALLBACK, CC_STATE_SUSPENDED) {
Prolog {
/* Start T_CCBS5/T_CCNR5 depending upon CC mode. */
Action Start_T_SUPERVISION;
}
Epilog {
Action Stop_T_SUPERVISION;
}
Stimulus CC_EVENT_RECALL {
/* Received CCBS_T_Call */
Action Pass_Up_CC_Call;
Action Set_Original_Call_Parameters;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Hangup_Signaling_Link;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Next_State CC_STATE_IDLE;
}
}
}

View File

@@ -0,0 +1,191 @@
/*
* FSM pseudo code used in the design/implementation of the CC PTP agent.
*/
FSM CC_PTP_Agent
{
State CC_STATE_IDLE {
Stimulus CC_EVENT_AVAILABLE {
Next_State CC_STATE_PENDING_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
}
}
State CC_STATE_PENDING_AVAILABLE {
Stimulus CC_EVENT_MSG_ALERTING {
Action Send_CC_Available(Q931_ALERTING);
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_MSG_DISCONNECT {
Action Send_CC_Available(Q931_DISCONNECT);
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_AVAILABLE {
/*
* For PTP mode the T_RETENTION timer is not defined. However,
* we will use it anyway in this state to protect our resources
* from leaks caused by user A not requesting CC. This timer
* should be set much longer than the PTMP network link to
* allow for variations in user A's CC offer timer.
*/
Stimulus CC_EVENT_MSG_RELEASE {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_MSG_RELEASE_COMPLETE {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_CC_REQUEST {
Action Pass_Up_CC_Request;
Action Stop_T_RETENTION;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_TIMEOUT_T_RETENTION {
Action Pass_Up_CC_Cancel;
Action Stop_T_RETENTION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Stop_T_RETENTION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_REQUESTED {
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
/* Start T_CCBS5/T_CCNR5 depending upon CC mode. */
Action Start_T_SUPERVISION;
Action Reset_A_Status;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Pass_Up_CC_Cancel;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_ACTIVATED {
Stimulus CC_EVENT_REMOTE_USER_FREE {
Action Pass_Up_A_Status_Indirect;
Test = Get_A_Status;
Test == Busy {
Next_State CC_STATE_SUSPENDED;
}
Action Send_RemoteUserFree;
Next_State CC_STATE_WAIT_CALLBACK;
}
Stimulus CC_EVENT_SUSPEND {
/* Received CCBS_T_Suspend */
Action Set_A_Status_Busy;
}
Stimulus CC_EVENT_RESUME {
/* Received CCBS_T_Resume */
Action Reset_A_Status;
}
Stimulus CC_EVENT_RECALL {
/* Received CCBS_T_Call */
Action Pass_Up_CC_Call;
Action Set_Original_Call_Parameters;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Hangup_Signaling_Link;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Pass_Up_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_WAIT_CALLBACK {
Stimulus CC_EVENT_SUSPEND {
/* Received CCBS_T_Suspend */
Action Set_A_Status_Busy;
Action Pass_Up_A_Status;
Next_State CC_STATE_SUSPENDED;
}
Stimulus CC_EVENT_RECALL {
/* Received CCBS_T_Call */
Action Pass_Up_CC_Call;
Action Set_Original_Call_Parameters;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Hangup_Signaling_Link;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Pass_Up_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_SUSPENDED {
Stimulus CC_EVENT_RESUME {
/* Received CCBS_T_Resume */
Action Set_A_Status_Free;
Action Pass_Up_A_Status;
Action Reset_A_Status;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_RECALL {
/* Received CCBS_T_Call */
Action Pass_Up_CC_Call;
Action Set_Original_Call_Parameters;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Hangup_Signaling_Link;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Pass_Up_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
}

168
doc/cc_ptp_monitor.fsm Normal file
View File

@@ -0,0 +1,168 @@
/*
* FSM pseudo code used in the design/implementation of the CC PTP monitor.
*/
FSM CC_PTP_Monitor
{
State CC_STATE_IDLE {
Init {
}
Prolog {
Action Set_Selfdestruct;
}
Stimulus CC_EVENT_AVAILABLE {
/* Received CCBS-T-Aailable */
Action Pass_Up_CC_Available;
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
}
}
State CC_STATE_AVAILABLE {
/*
* The upper layer is responsible for canceling the CC available
* offering.
*/
Stimulus CC_EVENT_CC_REQUEST {
/*
* Before event is posted:
* cc_record->is_ccnr is set.
* The signaling connection call record is created.
*/
Action Queue_CC_Request;
/*
* For PTP mode the T_ACTIVATE timer is not defined. However,
* we will use it to protect our resources from leaks caused
* by the network cable being disconnected.
* This timer should be set longer than normal so the
* CC records will normally be cleaned up by network activity.
*/
Action Start_T_ACTIVATE;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_CANCEL {
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_REQUESTED {
Epilog {
Action Stop_T_ACTIVATE;
}
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
/*
* Received CCBS-T-Request/CCNR-T-Request response
* Before event is posted:
* Negotiated CC retention setting saved
*/
Action Pass_Up_CC_Req_Rsp_Success;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_CC_REQUEST_FAIL {
Action Pass_Up_CC_Req_Rsp_Fail(error/reject, code);
Action Pass_Up_CC_Cancel;
/*
* If this request fail comes in with the RELEASE_COMPLETE
* message then the post action will never get a chance to
* run. It will be aborted because the CC_EVENT_SIGNALING_GONE
* will be processed first.
*/
Action Post_HANGUP_SIGNALING;
Next_State CC_STATE_WAIT_DESTRUCTION;
}
Stimulus CC_EVENT_TIMEOUT_T_ACTIVATE {
Action Pass_Up_CC_Req_Rsp_Timeout;
Action Pass_Up_CC_Cancel;
Action Hangup_Signaling_Link;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Claim it was a timeout */
Action Pass_Up_CC_Req_Rsp_Timeout;
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_WAIT_DESTRUCTION {
/*
* Delayed disconnect of the signaling link to allow subcmd events
* from the signaling link to be passed up.
*/
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_HANGUP_SIGNALING {
Action Hangup_Signaling_Link;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_ACTIVATED {
Prolog {
Action Reset_A_Status;
}
Stimulus CC_EVENT_REMOTE_USER_FREE {
/* Received CCBS_T_RemoteUserFree */
Action Pass_Up_Remote_User_Free;
Test = Get_A_Status;
Test == Busy {
Next_State CC_STATE_SUSPENDED;
}
Next_State CC_STATE_WAIT_CALLBACK;
}
Stimulus CC_EVENT_SUSPEND {
Action Set_A_Status_Busy;
}
Stimulus CC_EVENT_RESUME {
Action Reset_A_Status;
}
}
State CC_STATE_WAIT_CALLBACK {
Stimulus CC_EVENT_SUSPEND {
Next_State CC_STATE_SUSPENDED;
}
}
State CC_STATE_SUSPENDED {
Prolog {
Action Send_CC_Suspend;
}
Stimulus CC_EVENT_RESUME {
Action Send_CC_Resume;
Next_State CC_STATE_ACTIVATED;
}
}
Superstate CC_ACTIVE(CC_STATE_ACTIVATED, CC_STATE_WAIT_CALLBACK, CC_STATE_SUSPENDED) {
Prolog {
/* Start T_CCBS6/T_CCNR6 depending upon CC mode. */
Action Start_T_SUPERVISION;
}
Epilog {
Action Stop_T_SUPERVISION;
}
Stimulus CC_EVENT_RECALL {
/* The original call parameters have already been set. */
Action Queue_SETUP_Recall;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Hangup_Signaling_Link;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Next_State CC_STATE_IDLE;
}
}
}

View File

@@ -0,0 +1,217 @@
/*
* FSM pseudo code used in the design/implementation of the CC PTP monitor.
*/
FSM CC_PTP_Monitor
{
State CC_STATE_IDLE {
Stimulus CC_EVENT_AVAILABLE {
/* Received CCBS-T-Aailable */
Action Pass_Up_CC_Available;
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
}
}
State CC_STATE_AVAILABLE {
/*
* The upper layer is responsible for canceling the CC available
* offering.
*/
Stimulus CC_EVENT_CC_REQUEST {
/*
* Before event is posted:
* cc_record->is_ccnr is set.
* The signaling connection call record is created.
*/
Action Queue_CC_Request;
/*
* For PTP mode the T_ACTIVATE timer is not defined. However,
* we will use it to protect our resources from leaks caused
* by the network cable being disconnected.
* This timer should be set longer than normal so the
* CC records will normally be cleaned up by network activity.
*/
Action Start_T_ACTIVATE;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_REQUESTED {
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
/*
* Received CCBS-T-Request/CCNR-T-Request response
* Before event is posted:
* Negotiated CC retention setting saved
*/
Action Pass_Up_CC_Req_Rsp_Success;
Action Stop_T_ACTIVATE;
/* Start T_CCBS6/T_CCNR6 depending upon CC mode. */
Action Start_T_SUPERVISION;
Action Reset_A_Status;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_CC_REQUEST_FAIL {
Action Pass_Up_CC_Req_Rsp_Fail(error/reject, code);
Action Pass_Up_CC_Cancel;
/*
* If this request fail comes in with the RELEASE_COMPLETE
* message then the post action will never get a chance to
* run. It will be aborted because the CC_EVENT_SIGNALING_GONE
* will be processed first.
*/
Action Post_HANGUP_SIGNALING;
Action Stop_T_ACTIVATE;
Next_State CC_STATE_WAIT_DESTRUCTION;
}
Stimulus CC_EVENT_TIMEOUT_T_ACTIVATE {
Action Pass_Up_CC_Req_Rsp_Timeout;
Action Pass_Up_CC_Cancel;
Action Hangup_Signaling_Link;
Action Stop_T_ACTIVATE;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Claim it was a timeout */
Action Pass_Up_CC_Req_Rsp_Timeout;
Action Pass_Up_CC_Cancel;
Action Stop_T_ACTIVATE;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Action Stop_T_ACTIVATE;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_WAIT_DESTRUCTION {
/*
* Delayed disconnect of the signaling link to allow subcmd events
* from the signaling link to be passed up.
*/
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_HANGUP_SIGNALING {
Action Hangup_Signaling_Link;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_ACTIVATED {
Stimulus CC_EVENT_REMOTE_USER_FREE {
/* Received CCBS_T_RemoteUserFree */
Action Pass_Up_Remote_User_Free;
Test = Get_A_Status;
Test == Busy {
Action Send_CC_Suspend;
Next_State CC_STATE_SUSPENDED;
}
Next_State CC_STATE_WAIT_CALLBACK;
}
Stimulus CC_EVENT_SUSPEND {
Action Set_A_Status_Busy;
}
Stimulus CC_EVENT_RESUME {
Action Reset_A_Status;
}
Stimulus CC_EVENT_RECALL {
/* The original call parameters have already been set. */
Action Queue_SETUP_Recall;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Hangup_Signaling_Link;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Pass_Up_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_WAIT_CALLBACK {
Stimulus CC_EVENT_SUSPEND {
Action Send_CC_Suspend;
Next_State CC_STATE_SUSPENDED;
}
Stimulus CC_EVENT_RECALL {
/* The original call parameters have already been set. */
Action Queue_SETUP_Recall;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Hangup_Signaling_Link;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Pass_Up_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_SUSPENDED {
Stimulus CC_EVENT_RESUME {
Action Send_CC_Resume;
Action Reset_A_Status;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_RECALL {
/* The original call parameters have already been set. */
Action Queue_SETUP_Recall;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Hangup_Signaling_Link;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Pass_Up_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
}

136
doc/cc_qsig_agent.fsm Normal file
View File

@@ -0,0 +1,136 @@
/*
* FSM pseudo code used in the design/implementation of the CC Q.SIG agent.
*/
FSM CC_QSIG_Agent
{
State CC_STATE_IDLE {
Init {
}
Prolog {
Action Set_Selfdestruct;
}
Stimulus CC_EVENT_AVAILABLE {
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
}
}
State CC_STATE_AVAILABLE {
/*
* For Q.SIG mode the T_RETENTION timer is not defined. However,
* we will use it anyway in this state to protect our resources
* from leaks caused by user A not requesting CC. This timer
* should be set much longer than the PTMP network link to
* allow for variations in user A's CC offer timer.
*/
Epilog {
Action Stop_T_RETENTION;
}
Stimulus CC_EVENT_MSG_RELEASE {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_MSG_RELEASE_COMPLETE {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_CC_REQUEST {
Action Pass_Up_CC_Request;
/* Send Q931_CALL_PROCEEDING message on signaling link. */
Action Send_Call_Proceeding;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_TIMEOUT_T_RETENTION {
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_REQUESTED {
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_WAIT_DESTRUCTION {
/*
* Delayed disconnect of the signaling link to allow subcmd events
* from the signaling link to be passed up.
*/
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_HANGUP_SIGNALING {
Action Hangup_Signaling_Link;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_ACTIVATED {
Stimulus CC_EVENT_REMOTE_USER_FREE {
/* Send ccExecPossible in FACILITY or SETUP. */
Action Send_RemoteUserFree;
Next_State CC_STATE_WAIT_CALLBACK;
}
}
State CC_STATE_WAIT_CALLBACK {
Stimulus CC_EVENT_SUSPEND {
/* Received ccSuspend */
Action Set_A_Status_Busy;
Action Pass_Up_A_Status;
Next_State CC_STATE_SUSPENDED;
}
Stimulus CC_EVENT_RECALL {
/* Received ccRingout */
Action Pass_Up_CC_Call;
Action Set_Original_Call_Parameters;
}
}
State CC_STATE_SUSPENDED {
Stimulus CC_EVENT_RESUME {
/* Received ccResume */
Action Set_A_Status_Free;
Action Pass_Up_A_Status;
Next_State CC_STATE_ACTIVATED;
}
}
Superstate CC_ACTIVE(CC_STATE_ACTIVATED, CC_STATE_WAIT_CALLBACK, CC_STATE_SUSPENDED) {
Prolog {
/* Start QSIG_CCBS_T2/QSIG_CCNR_T2 depending upon CC mode. */
Action Start_T_SUPERVISION;
}
Epilog {
Action Stop_T_SUPERVISION;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Disassociate_Signaling_Link;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received ccCancel */
Action Pass_Up_CC_Cancel;
Action Post_HANGUP_SIGNALING;
Next_State CC_STATE_WAIT_DESTRUCTION;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CC_Cancel;
Next_State CC_STATE_IDLE;
}
}
}

View File

@@ -0,0 +1,183 @@
/*
* FSM pseudo code used in the design/implementation of the CC Q.SIG agent.
*/
FSM CC_QSIG_Agent
{
State CC_STATE_IDLE {
Stimulus CC_EVENT_AVAILABLE {
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
}
}
State CC_STATE_AVAILABLE {
/*
* For Q.SIG mode the T_RETENTION timer is not defined. However,
* we will use it anyway in this state to protect our resources
* from leaks caused by user A not requesting CC. This timer
* should be set much longer than the PTMP network link to
* allow for variations in user A's CC offer timer.
*/
Stimulus CC_EVENT_MSG_RELEASE {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_MSG_RELEASE_COMPLETE {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_CC_REQUEST {
Action Pass_Up_CC_Request;
/* Send Q931_CALL_PROCEEDING message on signaling link. */
Action Send_Call_Proceeding;
Action Stop_T_RETENTION;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_TIMEOUT_T_RETENTION {
Action Pass_Up_CC_Cancel;
Action Stop_T_RETENTION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Stop_T_RETENTION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_REQUESTED {
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
/* Start QSIG_CCBS_T2/QSIG_CCNR_T2 depending upon CC mode. */
Action Start_T_SUPERVISION;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Pass_Up_CC_Cancel;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_WAIT_DESTRUCTION {
/*
* Delayed disconnect of the signaling link to allow subcmd events
* from the signaling link to be passed up.
*/
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_HANGUP_SIGNALING {
Action Hangup_Signaling_Link;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_ACTIVATED {
Stimulus CC_EVENT_REMOTE_USER_FREE {
/* Send ccExecPossible in FACILITY or SETUP. */
Action Send_RemoteUserFree;
Next_State CC_STATE_WAIT_CALLBACK;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Disassociate_Signaling_Link;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received ccCancel */
Action Pass_Up_CC_Cancel;
Action Post_HANGUP_SIGNALING;
Action Stop_T_SUPERVISION;
Next_State CC_STATE_WAIT_DESTRUCTION;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_WAIT_CALLBACK {
Stimulus CC_EVENT_SUSPEND {
/* Received ccSuspend */
Action Set_A_Status_Busy;
Action Pass_Up_A_Status;
Next_State CC_STATE_SUSPENDED;
}
Stimulus CC_EVENT_RECALL {
/* Received ccRingout */
Action Pass_Up_CC_Call;
Action Set_Original_Call_Parameters;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Disassociate_Signaling_Link;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received ccCancel */
Action Pass_Up_CC_Cancel;
Action Post_HANGUP_SIGNALING;
Action Stop_T_SUPERVISION;
Next_State CC_STATE_WAIT_DESTRUCTION;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_SUSPENDED {
Stimulus CC_EVENT_RESUME {
/* Received ccResume */
Action Set_A_Status_Free;
Action Pass_Up_A_Status;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Disassociate_Signaling_Link;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received ccCancel */
Action Pass_Up_CC_Cancel;
Action Post_HANGUP_SIGNALING;
Action Stop_T_SUPERVISION;
Next_State CC_STATE_WAIT_DESTRUCTION;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
}

249
doc/cc_qsig_monitor.fsm Normal file
View File

@@ -0,0 +1,249 @@
/*
* FSM pseudo code used in the design/implementation of the CC Q.SIG monitor.
*/
FSM CC_QSIG_Monitor
{
State CC_STATE_IDLE {
Init {
}
Prolog {
Action Set_Selfdestruct;
}
Stimulus CC_EVENT_AVAILABLE {
/*
* LibPRI will determine if CC will be offered based upon
* if it is even possible.
* Essentially:
* 1) The call must not have been redirected in this link's
* setup.
* 2) Received an ALERTING or received a
* DISCONNECT(busy/congestion).
*/
Action Pass_Up_CC_Available;
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
}
}
State CC_STATE_AVAILABLE {
/*
* The upper layer is responsible for canceling the CC available
* offering.
*/
Stimulus CC_EVENT_CC_REQUEST {
/*
* Before event is posted:
* cc_record->is_ccnr is set.
* The signaling connection call record is created.
*/
Action Queue_CC_Request;
/* Start QSIG_CC_T1. */
Action Start_T_ACTIVATE;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_CANCEL {
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_REQUESTED {
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
/*
* Received ccbsRequest/ccnrRequest response
* Before event is posted:
* Negotiated CC retention setting saved
* Negotiated signaling link retention setting saved
*/
Action Stop_T_ACTIVATE;
Test = Get_msgtype;
Test == Q931_RELEASE {
Action Disassociate_Signaling_Link;
Test = Get_Retain_Signaling_Link;
Test == TRUE {
/*
* The far end did not honor the
* signaling link retention requirement.
* ECMA-186 Section 6.5.2.2.1
*/
Action Pass_Up_CC_Req_Rsp_Timeout;
Action Pass_Up_CC_Cancel;
Action Send_CC_Cancel;
Next_State CC_STATE_IDLE;
}
}
Action Pass_Up_CC_Req_Rsp_Success;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_CC_REQUEST_FAIL {
Action Stop_T_ACTIVATE;
Action Pass_Up_CC_Req_Rsp_Fail(error/reject, code);
Action Pass_Up_CC_Cancel;
/*
* If this request fail comes in with the RELEASE message
* then the post action will never get a chance to run.
* It will be aborted because the CC_EVENT_SIGNALING_GONE
* will be processed first.
*/
Action Post_HANGUP_SIGNALING;
Next_State CC_STATE_WAIT_DESTRUCTION;
}
Stimulus CC_EVENT_TIMEOUT_T_ACTIVATE {
Action Stop_T_ACTIVATE;
Action Pass_Up_CC_Req_Rsp_Timeout;
Action Pass_Up_CC_Cancel;
Action Hangup_Signaling_Link;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
Action Stop_T_ACTIVATE;
/* Claim it was a timeout */
Action Pass_Up_CC_Req_Rsp_Timeout;
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Next_State CC_STATE_WAIT_DESTRUCTION;
}
}
State CC_STATE_WAIT_DESTRUCTION {
/*
* Delayed disconnect of the signaling link to allow subcmd events
* from the signaling link to be passed up.
*/
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
/*
* Received ccbsRequest/ccnrRequest response
* Before event is posted:
* Negotiated CC retention setting saved
* Negotiated signaling link retention setting saved
*/
Action Stop_T_ACTIVATE;
Test = Get_msgtype;
Test == Q931_RELEASE {
Action Disassociate_Signaling_Link;
}
Action Send_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CC_REQUEST_FAIL {
Action Stop_T_ACTIVATE;
/*
* If this request fail comes in with the RELEASE message
* then the post action will never get a chance to run.
* It will be aborted because the CC_EVENT_SIGNALING_GONE
* will be processed first.
*/
Action Post_HANGUP_SIGNALING;
}
Stimulus CC_EVENT_TIMEOUT_T_ACTIVATE {
Action Stop_T_ACTIVATE;
Action Hangup_Signaling_Link;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Stop_T_ACTIVATE;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_HANGUP_SIGNALING {
//Action Stop_T_ACTIVATE;
Action Hangup_Signaling_Link;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_ACTIVATED {
Prolog {
Action Reset_A_Status;
}
Stimulus CC_EVENT_REMOTE_USER_FREE {
/* Received ccExecPossible */
Action Pass_Up_Remote_User_Free;
/*
* ECMA-186 Section 6.5.2.1.7
* Implied switch to retain-signaling-link.
*/
Action Set_Retain_Signaling_Link;
Test = Get_msgtype;
Test == Q931_SETUP {
/* Send Q931_CALL_PROCEEDING message on signaling link. */
Action Send_Call_Proceeding;
}
Test = Get_A_Status;
Test == Busy {
Next_State CC_STATE_SUSPENDED;
}
Next_State CC_STATE_WAIT_CALLBACK;
}
Stimulus CC_EVENT_SUSPEND {
Action Set_A_Status_Busy;
}
Stimulus CC_EVENT_RESUME {
Action Reset_A_Status;
}
}
State CC_STATE_WAIT_CALLBACK {
Prolog {
/* Start QSIG_CC_T3 */
Action Start_T_RECALL;
}
Epilog {
Action Stop_T_RECALL;
}
Stimulus CC_EVENT_RECALL {
/* The original call parameters have already been set. */
Action Queue_SETUP_Recall;
Next_State CC_STATE_CALLBACK;
}
Stimulus CC_EVENT_SUSPEND {
Next_State CC_STATE_SUSPENDED;
}
Stimulus CC_EVENT_TIMEOUT_T_RECALL {
Action Pass_Up_CC_Cancel;
Action Send_CC_Cancel;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_CALLBACK {
}
State CC_STATE_SUSPENDED {
Prolog {
/*
* The ccSuspend will be sent in a FACILITY or CONNECT
* message depending upon the CIS call state.
*/
Action Send_CC_Suspend;
}
Stimulus CC_EVENT_RESUME {
Action Send_CC_Resume;
Next_State CC_STATE_ACTIVATED;
}
}
Superstate CC_ACTIVE(CC_STATE_ACTIVATED, CC_STATE_WAIT_CALLBACK, CC_STATE_CALLBACK, CC_STATE_SUSPENDED) {
Prolog {
/* Start QSIG_CCBS_T2/QSIG_CCNR_T2 depending upon CC mode. */
Action Start_T_SUPERVISION;
}
Epilog {
Action Stop_T_SUPERVISION;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Disassociate_Signaling_Link;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received ccCancel */
Action Pass_Up_CC_Cancel;
Action Post_HANGUP_SIGNALING;
Next_State CC_STATE_WAIT_DESTRUCTION;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CC_Cancel;
Next_State CC_STATE_IDLE;
}
}
}

View File

@@ -0,0 +1,327 @@
/*
* FSM pseudo code used in the design/implementation of the CC Q.SIG monitor.
*/
FSM CC_QSIG_Monitor
{
State CC_STATE_IDLE {
Stimulus CC_EVENT_AVAILABLE {
/*
* LibPRI will determine if CC will be offered based upon
* if it is even possible.
* Essentially:
* 1) The call must not have been redirected in this link's
* setup.
* 2) Received an ALERTING or received a
* DISCONNECT(busy/congestion).
*/
Action Pass_Up_CC_Available;
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
}
}
State CC_STATE_AVAILABLE {
/*
* The upper layer is responsible for canceling the CC available
* offering.
*/
Stimulus CC_EVENT_CC_REQUEST {
/*
* Before event is posted:
* cc_record->is_ccnr is set.
* The signaling connection call record is created.
*/
Action Queue_CC_Request;
/* Start QSIG_CC_T1. */
Action Start_T_ACTIVATE;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_REQUESTED {
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
/*
* Received ccbsRequest/ccnrRequest response
* Before event is posted:
* Negotiated CC retention setting saved
* Negotiated signaling link retention setting saved
*/
Action Stop_T_ACTIVATE;
Test = Get_msgtype;
Test == Q931_RELEASE {
Action Disassociate_Signaling_Link;
Test = Get_Retain_Signaling_Link;
Test == TRUE {
/*
* The far end did not honor the
* signaling link retention requirement.
* ECMA-186 Section 6.5.2.2.1
*/
Action Pass_Up_CC_Req_Rsp_Timeout;
Action Pass_Up_CC_Cancel;
Action Send_CC_Cancel;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
Action Pass_Up_CC_Req_Rsp_Success;
/* Start QSIG_CCBS_T2/QSIG_CCNR_T2 depending upon CC mode. */
Action Start_T_SUPERVISION;
Action Reset_A_Status;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_CC_REQUEST_FAIL {
Action Stop_T_ACTIVATE;
Action Pass_Up_CC_Req_Rsp_Fail(error/reject, code);
Action Pass_Up_CC_Cancel;
/*
* If this request fail comes in with the RELEASE message
* then the post action will never get a chance to run.
* It will be aborted because the CC_EVENT_SIGNALING_GONE
* will be processed first.
*/
Action Post_HANGUP_SIGNALING;
Next_State CC_STATE_WAIT_DESTRUCTION;
}
Stimulus CC_EVENT_TIMEOUT_T_ACTIVATE {
Action Stop_T_ACTIVATE;
Action Pass_Up_CC_Req_Rsp_Timeout;
Action Pass_Up_CC_Cancel;
Action Hangup_Signaling_Link;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
Action Stop_T_ACTIVATE;
/* Claim it was a timeout */
Action Pass_Up_CC_Req_Rsp_Timeout;
Action Pass_Up_CC_Cancel;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Next_State CC_STATE_WAIT_DESTRUCTION;
}
}
State CC_STATE_WAIT_DESTRUCTION {
/*
* Delayed disconnect of the signaling link to allow subcmd events
* from the signaling link to be passed up.
*/
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
/*
* Received ccbsRequest/ccnrRequest response
* Before event is posted:
* Negotiated CC retention setting saved
* Negotiated signaling link retention setting saved
*/
Action Stop_T_ACTIVATE;
Test = Get_msgtype;
Test == Q931_RELEASE {
Action Disassociate_Signaling_Link;
}
Action Send_CC_Cancel;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CC_REQUEST_FAIL {
Action Stop_T_ACTIVATE;
/*
* If this request fail comes in with the RELEASE message
* then the post action will never get a chance to run.
* It will be aborted because the CC_EVENT_SIGNALING_GONE
* will be processed first.
*/
Action Post_HANGUP_SIGNALING;
}
Stimulus CC_EVENT_TIMEOUT_T_ACTIVATE {
Action Stop_T_ACTIVATE;
Action Hangup_Signaling_Link;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Stop_T_ACTIVATE;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_HANGUP_SIGNALING {
//Action Stop_T_ACTIVATE;
Action Hangup_Signaling_Link;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_ACTIVATED {
Stimulus CC_EVENT_REMOTE_USER_FREE {
/* Received ccExecPossible */
Action Pass_Up_Remote_User_Free;
/*
* ECMA-186 Section 6.5.2.1.7
* Implied switch to retain-signaling-link.
*/
Action Set_Retain_Signaling_Link;
Test = Get_msgtype;
Test == Q931_SETUP {
/* Send Q931_CALL_PROCEEDING message on signaling link. */
Action Send_Call_Proceeding;
}
Test = Get_A_Status;
Test == Busy {
/*
* The ccSuspend will be sent in a FACILITY or CONNECT
* message depending upon the CIS call state.
*/
Action Send_CC_Suspend;
Next_State CC_STATE_SUSPENDED;
}
/* Start QSIG_CC_T3 */
Action Start_T_RECALL;
Next_State CC_STATE_WAIT_CALLBACK;
}
Stimulus CC_EVENT_SUSPEND {
Action Set_A_Status_Busy;
}
Stimulus CC_EVENT_RESUME {
Action Reset_A_Status;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Disassociate_Signaling_Link;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received ccCancel */
Action Pass_Up_CC_Cancel;
Action Post_HANGUP_SIGNALING;
Action Stop_T_SUPERVISION;
Next_State CC_STATE_WAIT_DESTRUCTION;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_WAIT_CALLBACK {
Stimulus CC_EVENT_RECALL {
/* The original call parameters have already been set. */
Action Queue_SETUP_Recall;
Action Stop_T_RECALL;
Next_State CC_STATE_CALLBACK;
}
Stimulus CC_EVENT_SUSPEND {
Action Stop_T_RECALL;
/*
* The ccSuspend will be sent in a FACILITY or CONNECT
* message depending upon the CIS call state.
*/
Action Send_CC_Suspend;
Next_State CC_STATE_SUSPENDED;
}
Stimulus CC_EVENT_TIMEOUT_T_RECALL {
Action Pass_Up_CC_Cancel;
Action Send_CC_Cancel;
Action Stop_T_RECALL;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CC_Cancel;
Action Stop_T_RECALL;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Disassociate_Signaling_Link;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received ccCancel */
Action Pass_Up_CC_Cancel;
Action Post_HANGUP_SIGNALING;
Action Stop_T_RECALL;
Action Stop_T_SUPERVISION;
Next_State CC_STATE_WAIT_DESTRUCTION;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CC_Cancel;
Action Stop_T_RECALL;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_CALLBACK {
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Disassociate_Signaling_Link;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received ccCancel */
Action Pass_Up_CC_Cancel;
Action Post_HANGUP_SIGNALING;
Action Stop_T_SUPERVISION;
Next_State CC_STATE_WAIT_DESTRUCTION;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_SUSPENDED {
Stimulus CC_EVENT_RESUME {
Action Send_CC_Resume;
Action Reset_A_Status;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Disassociate_Signaling_Link;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received ccCancel */
Action Pass_Up_CC_Cancel;
Action Post_HANGUP_SIGNALING;
Action Stop_T_SUPERVISION;
Next_State CC_STATE_WAIT_DESTRUCTION;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
}

View File

@@ -0,0 +1,93 @@
<!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.12-beta2</title></head>
<body>
<h1 align="center"><a name="top">Release Summary</a></h1>
<h3 align="center">libpri-1.4.12-beta2</h3>
<h3 align="center">Date: 2010-08-30</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.12-beta1.</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>
13 rmudgett<br/>
1 alecdavis<br/>
1 mattf<br/>
</td>
<td>
1 jcovert<br/>
1 rmudgett<br/>
</td>
<td>
1 alecdavis<br/>
1 jcovert<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/view.php?id=16791">#16791</a>: [patch] q921_rnr_rx Q921_TIMER_RECOVERY SDL issue<br/>
Revision: <a href="http://svn.digium.com/view/libpri/branches/1.4?view=revision&revision=1845">1845</a><br/>
Reporter: alecdavis<br/>
Coders: alecdavis<br/>
<br/>
<a href="https://issues.asterisk.org/view.php?id=17570">#17570</a>: [patch] ISDN BRI does not recover from line faults<br/>
Revision: <a href="http://svn.digium.com/view/libpri/branches/1.4?view=revision&revision=1918">1918</a><br/>
Reporter: jcovert<br/>
Testers: jcovert, rmudgett<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=1842">1842</a></td><td>rmudgett</td><td>Renamed local struct pri *pri variables to struct pri *ctrl in q921.c.</td>
<td></td></tr><tr><td><a href="http://svn.digium.com/view/libpri/branches/1.4?view=revision&revision=1848">1848</a></td><td>rmudgett</td><td>Improved Q.921/Q.931 debug output.</td>
<td></td></tr><tr><td><a href="http://svn.digium.com/view/libpri/branches/1.4?view=revision&revision=1852">1852</a></td><td>rmudgett</td><td>Learn (AGAIN!) why state 7 and state 8 transitions were suppressed.</td>
<td></td></tr><tr><td><a href="http://svn.digium.com/view/libpri/branches/1.4?view=revision&revision=1853">1853</a></td><td>rmudgett</td><td>No audio on inbound J1 calls.</td>
<td></td></tr><tr><td><a href="http://svn.digium.com/view/libpri/branches/1.4?view=revision&revision=1878">1878</a></td><td>mattf</td><td>Add silly fake MDL error Z for kicking L2 to reactivate if a DISC or DM is received in proper states on PTP links.</td>
<td></td></tr><tr><td><a href="http://svn.digium.com/view/libpri/branches/1.4?view=revision&revision=1883">1883</a></td><td>rmudgett</td><td>Don't silently fail to post our fake MDL-ERROR(Z).</td>
<td></td></tr><tr><td><a href="http://svn.digium.com/view/libpri/branches/1.4?view=revision&revision=1884">1884</a></td><td>rmudgett</td><td>Added gripe check to rosetest for invalid operation and error codes.</td>
<td></td></tr><tr><td><a href="http://svn.digium.com/view/libpri/branches/1.4?view=revision&revision=1894">1894</a></td><td>rmudgett</td><td>Make pri_dump_event() only print the event name.</td>
<td></td></tr><tr><td><a href="http://svn.digium.com/view/libpri/branches/1.4?view=revision&revision=1904">1904</a></td><td>rmudgett</td><td>Add support to receive ECMA-164 2nd edition OID name ROSE messages.</td>
<td></td></tr><tr><td><a href="http://svn.digium.com/view/libpri/branches/1.4?view=revision&revision=1912">1912</a></td><td>rmudgett</td><td>Convert most references of Q931_MAX_TEI to use ARRAY_LEN().</td>
<td></td></tr><tr><td><a href="http://svn.digium.com/view/libpri/branches/1.4?view=revision&revision=1923">1923</a></td><td>rmudgett</td><td>Q.921 improvements from comparing Q.921 SDL diagrams with implementation.</td>
<td></td></tr><tr><td><a href="http://svn.digium.com/view/libpri/branches/1.4?view=revision&revision=1928">1928</a></td><td>rmudgett</td><td>Q.921/Q.931 message debug output improvements.</td>
<td></td></tr><tr><td><a href="http://svn.digium.com/view/libpri/branches/1.4?view=revision&revision=1929">1929</a></td><td>rmudgett</td><td>Reduced fake MDL-ERROR (Z) message severity to be visible only when debugging enabled.</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>
pri.c | 78 --
q921.c | 2135 ++++++++++++++++++++++++++++++++++++-------------------------
q931.c | 180 +++--
rose.c | 45 +
rosetest.c | 54 +
5 files changed, 1550 insertions(+), 942 deletions(-)
</pre><br/>
<hr/>
</body>
</html>

View File

@@ -0,0 +1,153 @@
Release Summary
libpri-1.4.12-beta2
Date: 2010-08-30
<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.12-beta1.
----------------------------------------------------------------------
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
13 rmudgett 1 jcovert 1 alecdavis
1 alecdavis 1 rmudgett 1 jcovert
1 mattf
----------------------------------------------------------------------
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
#16791: [patch] q921_rnr_rx Q921_TIMER_RECOVERY SDL issue
Revision: 1845
Reporter: alecdavis
Coders: alecdavis
#17570: [patch] ISDN BRI does not recover from line faults
Revision: 1918
Reporter: jcovert
Testers: jcovert, rmudgett
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 |
|----------+----------+-------------------------------------+------------|
| | | Renamed local struct pri *pri | |
| 1842 | rmudgett | variables to struct pri *ctrl in | |
| | | q921.c. | |
|----------+----------+-------------------------------------+------------|
| 1848 | rmudgett | Improved Q.921/Q.931 debug output. | |
|----------+----------+-------------------------------------+------------|
| | | Learn (AGAIN!) why state 7 and | |
| 1852 | rmudgett | state 8 transitions were | |
| | | suppressed. | |
|----------+----------+-------------------------------------+------------|
| 1853 | rmudgett | No audio on inbound J1 calls. | |
|----------+----------+-------------------------------------+------------|
| | | Add silly fake MDL error Z for | |
| 1878 | mattf | kicking L2 to reactivate if a DISC | |
| | | or DM is received in proper states | |
| | | on PTP links. | |
|----------+----------+-------------------------------------+------------|
| 1883 | rmudgett | Don't silently fail to post our | |
| | | fake MDL-ERROR(Z). | |
|----------+----------+-------------------------------------+------------|
| 1884 | rmudgett | Added gripe check to rosetest for | |
| | | invalid operation and error codes. | |
|----------+----------+-------------------------------------+------------|
| 1894 | rmudgett | Make pri_dump_event() only print | |
| | | the event name. | |
|----------+----------+-------------------------------------+------------|
| 1904 | rmudgett | Add support to receive ECMA-164 2nd | |
| | | edition OID name ROSE messages. | |
|----------+----------+-------------------------------------+------------|
| 1912 | rmudgett | Convert most references of | |
| | | Q931_MAX_TEI to use ARRAY_LEN(). | |
|----------+----------+-------------------------------------+------------|
| | | Q.921 improvements from comparing | |
| 1923 | rmudgett | Q.921 SDL diagrams with | |
| | | implementation. | |
|----------+----------+-------------------------------------+------------|
| 1928 | rmudgett | Q.921/Q.931 message debug output | |
| | | improvements. | |
|----------+----------+-------------------------------------+------------|
| | | Reduced fake MDL-ERROR (Z) message | |
| 1929 | rmudgett | severity to be visible only when | |
| | | debugging enabled. | |
+------------------------------------------------------------------------+
----------------------------------------------------------------------
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.
pri.c | 78 --
q921.c | 2135 ++++++++++++++++++++++++++++++++++++-------------------------
q931.c | 180 +++--
rose.c | 45 +
rosetest.c | 54 +
5 files changed, 1550 insertions(+), 942 deletions(-)
----------------------------------------------------------------------

778
libpri.h
View File

@@ -51,6 +51,7 @@
#define PRI_DEBUG_Q931_ANOMALY (1 << 7) /* Show unexpected events */
#define PRI_DEBUG_APDU (1 << 8) /* Debug of APDU components such as ROSE */
#define PRI_DEBUG_AOC (1 << 9) /* Debug of Advice of Charge ROSE Messages */
#define PRI_DEBUG_CC (1 << 10) /* Debug call-completion. */
#define PRI_DEBUG_ALL (0xffff) /* Everything */
@@ -97,6 +98,7 @@
#define PRI_EVENT_RETRIEVE 24 /* RETRIEVE request received */
#define PRI_EVENT_RETRIEVE_ACK 25 /* RETRIEVE_ACKNOWLEDGE received */
#define PRI_EVENT_RETRIEVE_REJ 26 /* RETRIEVE_REJECT received */
#define PRI_EVENT_CONNECT_ACK 27 /* CONNECT_ACKNOWLEDGE received */
/* Simple states */
#define PRI_STATE_DOWN 0
@@ -439,6 +441,14 @@ struct pri_party_subaddress {
unsigned char data[32];
};
/*! \brief Addressing information needed to identify an endpoint in a call. */
struct pri_party_address {
/*! \brief Subscriber phone number */
struct pri_party_number number;
/*! \brief Subscriber subaddress */
struct pri_party_subaddress subaddress;
};
/*! \brief Information needed to identify an endpoint in a call. */
struct pri_party_id {
/*! \brief Subscriber name */
@@ -503,11 +513,459 @@ struct pri_rerouting_data {
int invoke_id;
};
/* Subcommands derived from supplementary services. */
#define PRI_SUBCMD_REDIRECTING 1
#define PRI_SUBCMD_CONNECTED_LINE 2
#define PRI_SUBCMD_REROUTING 3
/*
* NOTE:
* The code surrounded by STATUS_REQUEST_PLACE_HOLDER is not implemented.
* The STATUS_REQUEST_PLACE_HOLDER code will be made unconditional if support
* for the messages is ever needed (and gets written).
*/
/* Subcommands derived from supplementary services. */
#define PRI_SUBCMD_REDIRECTING 1 /*!< Redirecting information update */
#define PRI_SUBCMD_CONNECTED_LINE 2 /*!< Connected line information update */
#define PRI_SUBCMD_REROUTING 3 /*!< CallRerouting/CallDeflection received. */
#if defined(STATUS_REQUEST_PLACE_HOLDER)
#define PRI_SUBCMD_STATUS_REQ 4 /*!< Determine the status of the given party. */
#define PRI_SUBCMD_STATUS_REQ_RSP 5 /*!< Status request response */
#endif /* defined(STATUS_REQUEST_PLACE_HOLDER) */
#define PRI_SUBCMD_CC_AVAILABLE 6 /*!< Indicate that CC is available */
#define PRI_SUBCMD_CC_REQ 7 /*!< CC activation request */
#define PRI_SUBCMD_CC_REQ_RSP 8 /*!< CC activation request response */
#define PRI_SUBCMD_CC_REMOTE_USER_FREE 9 /*!< Indicate that CC party B is available, party A is considered free. */
#define PRI_SUBCMD_CC_B_FREE 10 /*!< Indicate that CC party B is available, party A is considered busy. */
#define PRI_SUBCMD_CC_STATUS_REQ 11 /*!< Request/prod to receive updates of CC party A status */
#define PRI_SUBCMD_CC_STATUS_REQ_RSP 12 /*!< Requested update of CC party A status */
#define PRI_SUBCMD_CC_STATUS 13 /*!< Unsolicited update of CC party A status */
#define PRI_SUBCMD_CC_CALL 14 /*!< Indicate that this call is a CC callback */
#define PRI_SUBCMD_CC_CANCEL 15 /*!< Unsolicited indication that CC is canceled */
#define PRI_SUBCMD_CC_STOP_ALERTING 16 /*!< Indicate that someone else has responed to remote user free */
#define PRI_SUBCMD_TRANSFER_CALL 17 /*!< Request to transfer the specified calls together. */
#define PRI_SUBCMD_AOC_S 18 /*!< Advice Of Charge Start information (Rate list) */
#define PRI_SUBCMD_AOC_D 19 /*!< Advice Of Charge During information */
#define PRI_SUBCMD_AOC_E 20 /*!< Advice Of Charge End information */
#define PRI_SUBCMD_AOC_CHARGING_REQ 21 /*!< Advice Of Charge Request information */
#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 */
#if defined(STATUS_REQUEST_PLACE_HOLDER)
struct pri_subcmd_status_request {
/*!
* \brief Invoke id in case there are multiple outstanding requests.
* \note Used to match any responses with the original invoke in case
* there are several requests active.
*/
int invoke_id;
/*! \brief Party address requesting status about. */
struct pri_party_address party;
};
#endif /* defined(STATUS_REQUEST_PLACE_HOLDER) */
#if defined(STATUS_REQUEST_PLACE_HOLDER)
struct pri_subcmd_status_request_rsp {
/*!
* \brief Request id in case there are multiple outstanding requests.
* \note Used to match any responses with the request in case there
* are several requests active.
*/
int request_id;
/*!
* \brief Response status to the status request.
* \details
* free(0),
* busy(1),
* incompatible(2)
* timeout(3),
*/
int status;
};
#endif /* defined(STATUS_REQUEST_PLACE_HOLDER) */
struct pri_subcmd_cc_id {
/*! \brief Call-Completion record id */
long cc_id;
};
struct pri_subcmd_cc_request {
/*! \brief Call-Completion record id */
long cc_id;
/*!
* \brief Mode of call-completion requested.
* \details
* ccbs(0),
* ccnr(1)
*/
int mode;
};
struct pri_subcmd_cc_request_rsp {
/*! \brief Call-Completion record id */
long cc_id;
/*!
* \brief Status of the requested call-completion activation.
* \details
* success(0),
* timeout(1),
* error(2),
* reject(3)
*/
int status;
/*!
* \brief Failure code that can be converted to a string to further
* explain the non-timeout failure.
* \note Valid when status is error or reject.
* \note Use pri_facility_error2str() to convert the error_code.
* \note Use pri_facility_reject2str() to convert the reject_code.
*/
int fail_code;
};
struct pri_subcmd_cc_status {
/*! \brief Call-Completion record id */
long cc_id;
/*!
* \brief Party A status.
* \details
* free(0),
* busy(1)
*/
int status;
};
struct pri_subcmd_cc_cancel {
/*! \brief Call-Completion record id */
long cc_id;
/*!
* \brief TRUE if the cc_id is for an agent.
* \note This is a convenience value so the upper layer can know which
* list it should search for the cc_id.
*/
int is_agent;
};
struct pri_subcmd_transfer {
/*! \brief Opaque call pointer for transfer with other call. */
q931_call *call_1;
/*! \brief Opaque call pointer for transfer with other call. */
q931_call *call_2;
/*! TRUE if call_1 is on hold. */
int is_call_1_held;
/*! TRUE if call_2 is on hold. */
int is_call_2_held;
/*! Invocation ID to use when sending a reply to the transfer request. */
int invoke_id;
};
/*! \brief What is being charged. */
enum PRI_AOC_CHARGED_ITEM {
PRI_AOC_CHARGED_ITEM_NOT_AVAILABLE,
PRI_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT,
PRI_AOC_CHARGED_ITEM_BASIC_COMMUNICATION,
PRI_AOC_CHARGED_ITEM_CALL_ATTEMPT,
PRI_AOC_CHARGED_ITEM_CALL_SETUP,
PRI_AOC_CHARGED_ITEM_USER_USER_INFO,
PRI_AOC_CHARGED_ITEM_SUPPLEMENTARY_SERVICE,
};
/*! \brief Rate method being used. */
enum PRI_AOC_RATE_TYPE {
PRI_AOC_RATE_TYPE_NOT_AVAILABLE,
PRI_AOC_RATE_TYPE_FREE,
PRI_AOC_RATE_TYPE_FREE_FROM_BEGINNING,
PRI_AOC_RATE_TYPE_DURATION,
PRI_AOC_RATE_TYPE_FLAT,
PRI_AOC_RATE_TYPE_VOLUME,
PRI_AOC_RATE_TYPE_SPECIAL_CODE,
};
enum PRI_AOC_TIME_SCALE {
PRI_AOC_TIME_SCALE_HUNDREDTH_SECOND,
PRI_AOC_TIME_SCALE_TENTH_SECOND,
PRI_AOC_TIME_SCALE_SECOND,
PRI_AOC_TIME_SCALE_TEN_SECOND,
PRI_AOC_TIME_SCALE_MINUTE,
PRI_AOC_TIME_SCALE_HOUR,
PRI_AOC_TIME_SCALE_DAY,
};
struct pri_aoc_time {
/*! LengthOfTimeUnit (Not valid if length is zero.) */
long length;
/*! \see enum PRI_AOC_TIME_SCALE */
int scale;
};
enum PRI_AOC_MULTIPLIER {
PRI_AOC_MULTIPLIER_THOUSANDTH,
PRI_AOC_MULTIPLIER_HUNDREDTH,
PRI_AOC_MULTIPLIER_TENTH,
PRI_AOC_MULTIPLIER_ONE,
PRI_AOC_MULTIPLIER_TEN,
PRI_AOC_MULTIPLIER_HUNDRED,
PRI_AOC_MULTIPLIER_THOUSAND,
};
struct pri_aoc_amount {
long cost;
/*! \see enum PRI_AOC_MULTIPLIER */
int multiplier;
};
struct pri_aoc_duration {
struct pri_aoc_amount amount;
struct pri_aoc_time time;
/*! Not present if the granularity time is zero. */
struct pri_aoc_time granularity;
/*!
* \brief Charging interval type
* \details
* continuousCharging(0),
* stepFunction(1)
*/
int charging_type;
/*! Name of currency involved. Null terminated. */
char currency[10 + 1];
};
struct pri_aoc_flat {
struct pri_aoc_amount amount;
/*! Name of currency involved. Null terminated. */
char currency[10 + 1];
};
enum PRI_AOC_VOLUME_UNIT {
PRI_AOC_VOLUME_UNIT_OCTET,
PRI_AOC_VOLUME_UNIT_SEGMENT,
PRI_AOC_VOLUME_UNIT_MESSAGE,
};
struct pri_aoc_volume {
struct pri_aoc_amount amount;
/*! \see enum PRI_AOC_VOLUME_UNIT */
int unit;
/*! Name of currency involved. Null terminated. */
char currency[10 + 1];
};
struct pri_aoc_s_element {
/*!
* \brief What is being charged.
* \see enum PRI_AOC_CHARGED_ITEM
*/
int chargeable;
/*!
* \brief Rate method being used.
* \see enum PRI_AOC_RATE_TYPE
*/
int rate_type;
/*! \brief Charge rate being applied. */
union {
struct pri_aoc_duration duration;
struct pri_aoc_flat flat;
struct pri_aoc_volume volume;
int special;
} rate;
};
struct pri_subcmd_aoc_s {
/*!
* \brief Number of items in the rate list.
* \note If the list is empty then the charging information is not available.
*/
int num_items;
struct pri_aoc_s_element item[10];
};
enum PRI_AOC_DE_CHARGE {
PRI_AOC_DE_CHARGE_NOT_AVAILABLE,
PRI_AOC_DE_CHARGE_FREE,
PRI_AOC_DE_CHARGE_CURRENCY,
PRI_AOC_DE_CHARGE_UNITS,
};
struct pri_aoc_recorded_currency {
struct pri_aoc_amount amount;
/*! Name of currency involved. Null terminated. */
char currency[10 + 1];
};
struct pri_aoc_units_element {
/*! Number of units recorded. -1 if not available. */
long number;
/*! Type of unit recorded. -1 if not available. */
int type;
};
struct pri_aoc_recorded_units {
int num_items;
struct pri_aoc_units_element item[32];
};
enum PRI_AOC_D_BILLING_ID {
PRI_AOC_D_BILLING_ID_NOT_AVAILABLE,
PRI_AOC_D_BILLING_ID_NORMAL,
PRI_AOC_D_BILLING_ID_REVERSE,
PRI_AOC_D_BILLING_ID_CREDIT_CARD,
};
struct pri_subcmd_aoc_d {
/*!
* \brief What is being charged.
* \see enum PRI_AOC_DE_CHARGE
*/
int charge;
/*!
* \brief Billing accumulation
* \details
* subTotal(0),
* total(1)
*/
int billing_accumulation;
/*! \see enum PRI_AOC_D_BILLING_ID */
int billing_id;
union {
/*! Recorded currency */
struct pri_aoc_recorded_currency money;
/*! Recorded units list */
struct pri_aoc_recorded_units unit;
} recorded;
};
enum PRI_AOC_E_BILLING_ID {
PRI_AOC_E_BILLING_ID_NOT_AVAILABLE,
PRI_AOC_E_BILLING_ID_NORMAL,
PRI_AOC_E_BILLING_ID_REVERSE,
PRI_AOC_E_BILLING_ID_CREDIT_CARD,
PRI_AOC_E_BILLING_ID_CALL_FORWARDING_UNCONDITIONAL,
PRI_AOC_E_BILLING_ID_CALL_FORWARDING_BUSY,
PRI_AOC_E_BILLING_ID_CALL_FORWARDING_NO_REPLY,
PRI_AOC_E_BILLING_ID_CALL_DEFLECTION,
PRI_AOC_E_BILLING_ID_CALL_TRANSFER,
};
enum PRI_AOC_E_CHARGING_ASSOCIATION {
PRI_AOC_E_CHARGING_ASSOCIATION_NOT_AVAILABLE,
PRI_AOC_E_CHARGING_ASSOCIATION_NUMBER,
PRI_AOC_E_CHARGING_ASSOCIATION_ID,
};
struct pri_aoc_e_charging_association {
union {
/*! Charged number */
struct pri_party_number number;
/*! Charge identifier */
int id;
} charge;
/*! \see enum PRI_AOC_E_CHARGING_ASSOCIATION */
int charging_type;
};
struct pri_subcmd_aoc_e {
/*!
* \brief What is being charged.
* \see enum PRI_AOC_DE_CHARGE
*/
int charge;
/*! \see enum PRI_AOC_E_BILLING_ID */
int billing_id;
union {
/*! Recorded currency */
struct pri_aoc_recorded_currency money;
/*! Recorded units list */
struct pri_aoc_recorded_units unit;
} recorded;
/*! Charging association. */
struct pri_aoc_e_charging_association associated;
};
enum PRI_AOC_REQ_RSP {
/* Error Results */
PRI_AOC_REQ_RSP_ERROR_NOT_IMPLEMENTED,
PRI_AOC_REQ_RSP_ERROR_NOT_AVAILABLE,
PRI_AOC_REQ_RSP_ERROR_TIMEOUT,
PRI_AOC_REQ_RSP_ERROR_REJECT,
/* generic error result all other errors are lumped into */
PRI_AOC_REQ_RSP_ERROR,
/* AOC Results */
PRI_AOC_REQ_RSP_CHARGING_INFO_FOLLOWS,
PRI_AOC_REQ_RSP_CURRENCY_INFO_LIST,
PRI_AOC_REQ_RSP_SPECIAL_ARR,
};
enum PRI_AOC_REQUEST {
PRI_AOC_REQUEST_S = (1 << 0),
PRI_AOC_REQUEST_D = (1 << 1),
PRI_AOC_REQUEST_E = (1 << 2),
};
struct pri_subcmd_aoc_request_response {
/*!
* \brief aoc_s data from response
*/
struct pri_subcmd_aoc_s aoc_s;
/*!
* \brief if the aoc_s msg is present, this will be set
*/
int valid_aoc_s;
/*!
* \brief What type of aoc was requested.
* \see enum PRI_AOC_REQUEST
*/
int charging_request;
/*!
* \brief response to the charging_request
* \see enum PRI_AOC_REQ_RSP
*/
int charging_response;
};
struct pri_subcmd_aoc_request {
/*!
* \brief What types of aoc are being requested.
* \see enum PRI_AOC_REQUEST
*/
int charging_request;
/*!
* \brief Value given by the initiating request.
*/
int invoke_id;
};
struct pri_subcmd_mcid_req {
/*!
* \brief Information libpri knows about the malicious caller.
* \note For the convenience of the upper layer. This information
* may be incomplete if the upper layer redacted some caller
* information because it was restricted.
*/
struct pri_party_id originator;
/*! \brief Information libpri knows about the callee. */
struct pri_party_id answerer;
};
struct pri_subcmd_mcid_rsp {
/*!
* \brief MCID request response status.
* \details
* success(0),
* timeout(1),
* error(2),
* reject(3)
*/
int status;
/*!
* \brief Failure code that can be converted to a string to further
* explain the non-timeout failure.
* \note Valid when status is error or reject.
* \note Use pri_facility_error2str() to convert the error_code.
* \note Use pri_facility_reject2str() to convert the reject_code.
*/
int fail_code;
};
struct pri_subcommand {
/*! PRI_SUBCMD_xxx defined values */
@@ -518,6 +976,29 @@ struct pri_subcommand {
struct pri_party_connected_line connected_line;
struct pri_party_redirecting redirecting;
struct pri_rerouting_data rerouting;
#if defined(STATUS_REQUEST_PLACE_HOLDER)
struct pri_subcmd_status_request status_request;
struct pri_subcmd_status_request_rsp status_request_rsp;
#endif /* defined(STATUS_REQUEST_PLACE_HOLDER) */
struct pri_subcmd_cc_id cc_available;
struct pri_subcmd_cc_request cc_request;
struct pri_subcmd_cc_request_rsp cc_request_rsp;
struct pri_subcmd_cc_id cc_remote_user_free;
struct pri_subcmd_cc_id cc_b_free;
struct pri_subcmd_cc_id cc_stop_alerting;
struct pri_subcmd_cc_id cc_status_req;
struct pri_subcmd_cc_status cc_status_req_rsp;
struct pri_subcmd_cc_status cc_status;
struct pri_subcmd_cc_id cc_call;
struct pri_subcmd_cc_cancel cc_cancel;
struct pri_subcmd_transfer transfer;
struct pri_subcmd_aoc_request aoc_request;
struct pri_subcmd_aoc_request_response aoc_request_response;
struct pri_subcmd_aoc_s aoc_s;
struct pri_subcmd_aoc_d aoc_d;
struct pri_subcmd_aoc_e aoc_e;
struct pri_subcmd_mcid_req mcid_req;
struct pri_subcmd_mcid_rsp mcid_rsp;
} u;
};
@@ -662,7 +1143,7 @@ typedef struct pri_event_hangup {
int cause;
int cref;
q931_call *call; /* Opaque call pointer of call hanging up. */
long aoc_units; /* Advise of Charge number of charged units */
long aoc_units; /* Advice of Charge number of charged units */
char useruserinfo[260]; /* User->User info */
struct pri_subcommands *subcmds;
/*!
@@ -776,6 +1257,13 @@ struct pri_event_retrieve_rej {
struct pri_subcommands *subcmds;
};
struct pri_event_connect_ack {
int e;
int channel;
q931_call *call;
struct pri_subcommands *subcmds;
};
typedef union {
int e;
pri_event_generic gen; /* Generic view */
@@ -800,6 +1288,7 @@ typedef union {
struct pri_event_retrieve retrieve;
struct pri_event_retrieve_ack retrieve_ack;
struct pri_event_retrieve_rej retrieve_rej;
struct pri_event_connect_ack connect_ack;
} pri_event;
struct pri;
@@ -819,6 +1308,9 @@ struct pri *pri_new_bri(int fd, int ptpmode, int nodetype, int switchtype);
/* Create D-channel just as above with user defined I/O callbacks and data */
struct pri *pri_new_cb(int fd, int nodetype, int switchtype, pri_io_cb io_read, pri_io_cb io_write, void *userdata);
/* Create BRI D-channel just as above with user defined I/O callbacks and data */
struct pri *pri_new_bri_cb(int fd, int ptpmode, int nodetype, int switchtype, pri_io_cb io_read, pri_io_cb io_write, void *userdata);
/* Retrieve the user data associated with the D channel */
void *pri_get_userdata(struct pri *pri);
@@ -867,6 +1359,24 @@ char *pri_plan2str(int plan);
/* Turn cause into a string */
char *pri_cause2str(int cause);
/*!
* \brief Convert the given facility error code to a descriptive string.
*
* \param facility_error_code Error code to convert to a string.
*
* \return Descriptive error string.
*/
const char *pri_facility_error2str(int facility_error_code);
/*!
* \brief Convert the given facility reject code to a descriptive string.
*
* \param facility_reject_code Error code to convert to a string.
*
* \return Descriptive reject string.
*/
const char *pri_facility_reject2str(int facility_reject_code);
/* Acknowledge a call and place it on the given channel. Set info to non-zero if there
is in-band data available on the channel */
int pri_acknowledge(struct pri *pri, q931_call *call, int channel, int info);
@@ -882,10 +1392,33 @@ int pri_keypad_facility(struct pri *pri, q931_call *call, const char *digits);
Set non-isdn to non-zero if you are not connecting to ISDN equipment */
int pri_need_more_info(struct pri *pri, q931_call *call, int channel, int nonisdn);
/* Answer the call on the given channel (ignored if you called acknowledge already).
/* Answer(CONNECT) the call on the given channel.
Set non-isdn to non-zero if you are not connecting to ISDN equipment */
int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn);
/*!
* \brief Send the manual CONNECT_ACKNOWLEDGE message.
*
* \param ctrl D channel controller.
* \param call Q.931 call leg.
* \param channel Selected channel to assign to the call waiting call.
* Zero if do not include the channel id ie in the CONNECT_ACKNOWLEDGE message.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int pri_connect_ack(struct pri *ctrl, q931_call *call, int channel);
/*!
* \brief Set the manual CONNECT_ACKNOWLEDGE message enable flag.
*
* \param ctrl D channel controller.
* \param enable TRUE to enable manual CONNECT_ACKNOWLEDGE message feature.
*
* \return Nothing
*/
void pri_connect_ack_enable(struct pri *ctrl, int enable);
/*!
* \brief Give connected line information to a call
* \note Could be used instead of pri_sr_set_caller_party() before calling pri_setup().
@@ -1053,12 +1586,31 @@ int pri_mwi_activate(struct pri *pri, q931_call *c, char *caller, int callerplan
/* Send an MWI deactivate request to a remote location */
int pri_mwi_deactivate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called, int calledplan);
/*!
* \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 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 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(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);
/* Set service message support flag */
int pri_set_service_message_support(struct pri *pri, int supportflag);
#define PRI_2BCT
/* Attempt to pass the channels back to the NET side if compatable and
* suscribed. Sometimes called 2 bchannel transfer (2BCT) */
* subscribed. Sometimes called 2 bchannel transfer (2BCT) */
int pri_channel_bridge(q931_call *call1, q931_call *call2);
/* Override message and error stuff */
@@ -1098,6 +1650,79 @@ void pri_set_inbanddisconnect(struct pri *pri, unsigned int enable);
(and maybe some timers) */
void pri_enslave(struct pri *master, struct pri *slave);
/*!
* \brief Request AOC on call setup
*
* \param call setup struct to set charging request info on
* \param charging request to set on setup struct
*
* \retval 0 on success
* \retval -1 on failure
*/
int pri_sr_set_aoc_charging_request(struct pri_sr *sr, int charging_request);
/*!
* \brief Send AOC Request Response to a request for AOC-S
*
* \param ctrl D channel controller.
* \param call Q.931 call leg.
* \param invoke_id for response message
* \param aoc_s message for response
*
* \retval 0 on success
* \retval -1 on failure
*/
int pri_aoc_s_request_response_send(struct pri *ctrl, q931_call *call, int invoke_id, const struct pri_subcmd_aoc_s *aoc_s);
/*!
* \brief Send AOC Request Response to a request for AOC-D or AOC-E
*
* \param ctrl D channel controller.
* \param call Q.931 call leg.
* \param response in form of enum PRI_AOC_REQ_RSP
* \param invoke_id for response message
*
* \retval 0 on success
* \retval -1 on failure
*/
int pri_aoc_de_request_response_send(struct pri *ctrl, q931_call *call, int response, int invoke_id);
/*!
* \brief Send AOC-S message.
*
* \param ctrl D channel controller.
* \param call Q.931 call leg.
* \param aoc_s message to send
*
* \retval 0 on success
* \retval -1 on failure
*/
int pri_aoc_s_send(struct pri *ctrl, q931_call *c, const struct pri_subcmd_aoc_s *aoc_s);
/*!
* \brief Send AOC-D message.
*
* \param ctrl D channel controller.
* \param call Q.931 call leg.
* \param aoc_d message to send
*
* \retval 0 on success
* \retval -1 on failure
*/
int pri_aoc_d_send(struct pri *ctrl, q931_call *c, const struct pri_subcmd_aoc_d *aoc_d);
/*!
* \brief Send AOC-E message.
*
* \param ctrl D channel controller.
* \param call Q.931 call leg.
* \param aoc_e message to send
*
* \retval 0 on success
* \retval -1 on failure
*/
int pri_aoc_e_send(struct pri *ctrl, q931_call *c, const struct pri_subcmd_aoc_e *aoc_e);
#define PRI_GR303_SUPPORT
#define PRI_ENSLAVE_SUPPORT
#define PRI_SETUP_CALL
@@ -1182,6 +1807,39 @@ enum PRI_REROUTING_RSP_CODE {
*/
int pri_rerouting_rsp(struct pri *ctrl, q931_call *call, int invoke_id, enum PRI_REROUTING_RSP_CODE code);
/*!
* \brief Set the call transfer feature enable flag.
*
* \param ctrl D channel controller.
* \param enable TRUE to enable call transfer feature.
*
* \return Nothing
*/
void pri_transfer_enable(struct pri *ctrl, int enable);
/*!
* \brief Send the call transfer response message.
*
* \param ctrl D channel controller.
* \param call Q.931 call leg.
* \param invoke_id Value given by the initiating request.
* \param is_successful TRUE if the transfer was successful.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int pri_transfer_rsp(struct pri *ctrl, q931_call *call, int invoke_id, int is_successful);
/*!
* \brief Set the advice of charge events feature enable flag.
*
* \param ctrl D channel controller.
* \param enable TRUE to enable AOC events feature.
*
* \return Nothing
*/
void pri_aoc_events_enable(struct pri *ctrl, int enable);
/*!
* \brief Set the call hold feature enable flag.
*
@@ -1262,6 +1920,87 @@ int pri_retrieve_ack(struct pri *ctrl, q931_call *call, int channel);
*/
int pri_retrieve_rej(struct pri *ctrl, q931_call *call, int cause);
#if defined(STATUS_REQUEST_PLACE_HOLDER)
int pri_status_req(struct pri *ctrl, int request_id, const struct pri_sr *req);
void pri_status_req_rsp(struct pri *ctrl, int invoke_id, int status);
#endif /* defined(STATUS_REQUEST_PLACE_HOLDER) */
/*!
* \brief Set the Malicious Call ID feature enable flag.
*
* \param ctrl D channel controller.
* \param enable TRUE to enable MCID feature.
*
* \return Nothing
*/
void pri_mcid_enable(struct pri *ctrl, int enable);
/*!
* \brief Send the MCID request message.
*
* \param ctrl D channel controller.
* \param call Q.931 call leg
*
* \retval 0 on success. You should wait for a PRI_SUBCMD_MCID_RSP
* to continue clearing the call if it was in progress.
* \retval -1 on error.
*/
int pri_mcid_req_send(struct pri *ctrl, q931_call *call);
/*!
* \brief Set the call completion feature enable flag.
*
* \param ctrl D channel controller.
* \param enable TRUE to enable call completion feature.
*
* \return Nothing
*/
void pri_cc_enable(struct pri *ctrl, int enable);
/*!
* \brief Set the PTMP NT call completion recall mode.
*
* \param ctrl D channel controller.
* \param mode globalRecall(0), specificRecall(1)
*
* \return Nothing
*/
void pri_cc_recall_mode(struct pri *ctrl, int mode);
/*!
* \brief Set the Q.SIG call completion signaling link retention mode.
* (Requestor/Initiator/Originator/Party-A)
*
* \param ctrl D channel controller.
* \param signaling_retention release(0), retain(1), do-not-care(2).
*
* \return Nothing
*/
void pri_cc_retain_signaling_req(struct pri *ctrl, int signaling_retention);
/*!
* \brief Set the Q.SIG call completion signaling link retention mode.
* (Responder/Answerer/Party-B)
*
* \param ctrl D channel controller.
* \param signaling_retention release(0), retain(1).
*
* \return Nothing
*/
void pri_cc_retain_signaling_rsp(struct pri *ctrl, int signaling_retention);
long pri_cc_available(struct pri *ctrl, q931_call *call);
int pri_cc_req(struct pri *ctrl, long cc_id, int mode);
int pri_cc_req_rsp(struct pri *ctrl, long cc_id, int status);
void pri_cc_remote_user_free(struct pri *ctrl, long cc_id);
void pri_cc_b_free(struct pri *ctrl, long cc_id);
void pri_cc_stop_alerting(struct pri *ctrl, long cc_id);
void pri_cc_status_req(struct pri *ctrl, long cc_id);
void pri_cc_status_req_rsp(struct pri *ctrl, long cc_id, int status);
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);
/* Get/Set PRI Timers */
#define PRI_GETSET_TIMERS
int pri_set_timer(struct pri *pri, int timer, int value);
@@ -1309,6 +2048,31 @@ enum PRI_TIMERS_AND_COUNTERS {
PRI_TIMER_T_RESPONSE, /*!< Maximum time to wait for a typical APDU response. */
PRI_TIMER_T_STATUS, /*!< Max time to wait for all replies to check for compatible terminals */
PRI_TIMER_T_ACTIVATE, /*!< Request supervision timeout. */
PRI_TIMER_T_DEACTIVATE, /*!< Deactivate supervision timeout. */
PRI_TIMER_T_INTERROGATE,/*!< Interrogation supervision timeout. */
/* ETSI call-completion timers */
PRI_TIMER_T_RETENTION, /*!< Max time to wait for user A to activate call-completion. */
PRI_TIMER_T_CCBS1, /*!< T-STATUS timer equivalent for CC user A status. */
PRI_TIMER_T_CCBS2, /*!< Max time the CCBS service will be active */
PRI_TIMER_T_CCBS3, /*!< Max time to wait for user A to respond to user B availability. */
PRI_TIMER_T_CCBS4, /*!< CC user B guard time before sending CC recall indication. */
PRI_TIMER_T_CCBS5, /*!< Network B CCBS supervision timeout. */
PRI_TIMER_T_CCBS6, /*!< Network A CCBS supervision timeout. */
PRI_TIMER_T_CCNR2, /*!< Max time the CCNR service will be active */
PRI_TIMER_T_CCNR5, /*!< Network B CCNR supervision timeout. */
PRI_TIMER_T_CCNR6, /*!< Network A CCNR supervision timeout. */
/* Q.SIG call-completion timers */
PRI_TIMER_QSIG_CC_T1, /*!< CC request supervision timeout. */
PRI_TIMER_QSIG_CCBS_T2, /*!< CCBS supervision timeout. */
PRI_TIMER_QSIG_CCNR_T2, /*!< CCNR supervision timeout. */
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. */
/* Must be last in the enum list */
PRI_MAX_TIMERS
};

328
pri.c
View File

@@ -40,11 +40,10 @@
#include "libpri.h"
#include "pri_internal.h"
#include "pri_facility.h"
#include "pri_q921.h"
#include "pri_q931.h"
#define PRI_BIT(a_bit) (1UL << (a_bit))
#define PRI_ALL_SWITCHES 0xFFFFFFFF
#define PRI_ETSI_SWITCHES (PRI_BIT(PRI_SWITCH_EUROISDN_E1) | PRI_BIT(PRI_SWITCH_EUROISDN_T1))
struct pri_timer_table {
const char *name;
@@ -89,6 +88,27 @@ static const struct pri_timer_table pri_timer[] = {
{ "T-HOLD", PRI_TIMER_T_HOLD, PRI_ALL_SWITCHES },
{ "T-RETRIEVE", PRI_TIMER_T_RETRIEVE, PRI_ALL_SWITCHES },
{ "T-RESPONSE", PRI_TIMER_T_RESPONSE, PRI_ALL_SWITCHES },
{ "T-STATUS", PRI_TIMER_T_STATUS, PRI_ETSI_SWITCHES },
{ "T-ACTIVATE", PRI_TIMER_T_ACTIVATE, PRI_ETSI_SWITCHES },
{ "T-DEACTIVATE", PRI_TIMER_T_DEACTIVATE, PRI_ETSI_SWITCHES },
{ "T-INTERROGATE", PRI_TIMER_T_INTERROGATE, PRI_ETSI_SWITCHES },
{ "T-RETENTION", PRI_TIMER_T_RETENTION, PRI_ETSI_SWITCHES | PRI_BIT(PRI_SWITCH_QSIG) },
{ "T-CCBS1", PRI_TIMER_T_CCBS1, PRI_ETSI_SWITCHES },
{ "T-CCBS2", PRI_TIMER_T_CCBS2, PRI_ETSI_SWITCHES },
{ "T-CCBS3", PRI_TIMER_T_CCBS3, PRI_ETSI_SWITCHES },
{ "T-CCBS4", PRI_TIMER_T_CCBS4, PRI_ETSI_SWITCHES },
{ "T-CCBS5", PRI_TIMER_T_CCBS5, PRI_ETSI_SWITCHES },
{ "T-CCBS6", PRI_TIMER_T_CCBS6, PRI_ETSI_SWITCHES },
{ "T-CCNR2", PRI_TIMER_T_CCNR2, PRI_ETSI_SWITCHES },
{ "T-CCNR5", PRI_TIMER_T_CCNR5, PRI_ETSI_SWITCHES },
{ "T-CCNR6", PRI_TIMER_T_CCNR6, PRI_ETSI_SWITCHES },
{ "CC-T1", PRI_TIMER_QSIG_CC_T1, PRI_BIT(PRI_SWITCH_QSIG) },
{ "CCBS-T2", PRI_TIMER_QSIG_CCBS_T2, PRI_BIT(PRI_SWITCH_QSIG) },
{ "CCNR-T2", PRI_TIMER_QSIG_CCNR_T2, PRI_BIT(PRI_SWITCH_QSIG) },
{ "CC-T3", PRI_TIMER_QSIG_CC_T3, PRI_BIT(PRI_SWITCH_QSIG) },
#if defined(QSIG_PATH_RESERVATION_SUPPORT)
{ "CC-T4", PRI_TIMER_QSIG_CC_T4, PRI_BIT(PRI_SWITCH_QSIG) },
#endif /* defined(QSIG_PATH_RESERVATION_SUPPORT) */
/* *INDENT-ON* */
};
@@ -166,6 +186,33 @@ static void pri_default_timers(struct pri *ctrl, int switchtype)
ctrl->timers[PRI_TIMER_T_RESPONSE] = 4 * 1000; /* Maximum time to wait for a typical APDU response. */
/* ETSI timers */
ctrl->timers[PRI_TIMER_T_STATUS] = 4 * 1000; /* Max time to wait for all replies to check for compatible terminals */
ctrl->timers[PRI_TIMER_T_ACTIVATE] = 10 * 1000; /* Request supervision timeout. */
ctrl->timers[PRI_TIMER_T_DEACTIVATE] = 4 * 1000;/* Deactivate supervision timeout. */
ctrl->timers[PRI_TIMER_T_INTERROGATE] = 4 * 1000;/* Interrogation supervision timeout. */
/* ETSI call-completion timers */
ctrl->timers[PRI_TIMER_T_RETENTION] = 30 * 1000;/* Max time to wait for user A to activate call-completion. */
ctrl->timers[PRI_TIMER_T_CCBS1] = 4 * 1000; /* T-STATUS timer equivalent for CC user A status. */
ctrl->timers[PRI_TIMER_T_CCBS2] = 45 * 60 * 1000;/* Max time the CCBS service will be active */
ctrl->timers[PRI_TIMER_T_CCBS3] = 20 * 1000; /* Max time to wait for user A to respond to user B availability. */
ctrl->timers[PRI_TIMER_T_CCBS4] = 5 * 1000; /* CC user B guard time before sending CC recall indication. */
ctrl->timers[PRI_TIMER_T_CCBS5] = 60 * 60 * 1000;/* Network B CCBS supervision timeout. */
ctrl->timers[PRI_TIMER_T_CCBS6] = 60 * 60 * 1000;/* Network A CCBS supervision timeout. */
ctrl->timers[PRI_TIMER_T_CCNR2] = 180 * 60 * 1000;/* Max time the CCNR service will be active */
ctrl->timers[PRI_TIMER_T_CCNR5] = 195 * 60 * 1000;/* Network B CCNR supervision timeout. */
ctrl->timers[PRI_TIMER_T_CCNR6] = 195 * 60 * 1000;/* Network A CCNR supervision timeout. */
/* Q.SIG call-completion timers */
ctrl->timers[PRI_TIMER_QSIG_CC_T1] = 30 * 1000;/* CC request supervision timeout. */
ctrl->timers[PRI_TIMER_QSIG_CCBS_T2] = 60 * 60 * 1000;/* CCBS supervision timeout. */
ctrl->timers[PRI_TIMER_QSIG_CCNR_T2] = 195 * 60 * 1000;/* CCNR supervision timeout. */
ctrl->timers[PRI_TIMER_QSIG_CC_T3] = 30 * 1000;/* Max time to wait for user A to respond to user B availability. */
#if defined(QSIG_PATH_RESERVATION_SUPPORT)
ctrl->timers[PRI_TIMER_QSIG_CC_T4] = 40 * 1000;/* Path reservation supervision timeout. */
#endif /* defined(QSIG_PATH_RESERVATION_SUPPORT) */
/* Set any switch specific override default values */
switch (switchtype) {
default:
@@ -246,6 +293,7 @@ void __pri_free_tei(struct pri * p)
pri_call_apdu_queue_cleanup(call);
}
free(p->msg_line);
free(p->sched.timer);
free(p);
}
}
@@ -300,6 +348,7 @@ struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master,
pri_default_timers(p, switchtype);
if (master) {
pri_set_debug(p, master->debug);
pri_set_inbanddisconnect(p, master->acceptinbanddisconnect);
if (master->sendfacility)
pri_facility_enable(p);
}
@@ -408,6 +457,21 @@ struct pri *pri_new_cb(int fd, int nodetype, int switchtype, pri_io_cb io_read,
return __pri_new_tei(fd, nodetype, switchtype, NULL, io_read, io_write, userdata, Q921_TEI_PRI, 0);
}
struct pri *pri_new_bri_cb(int fd, int ptpmode, int nodetype, int switchtype, pri_io_cb io_read, pri_io_cb io_write, void *userdata)
{
if (!io_read) {
io_read = __pri_read;
}
if (!io_write) {
io_write = __pri_write;
}
if (ptpmode) {
return __pri_new_tei(fd, nodetype, switchtype, NULL, io_read, io_write, userdata, Q921_TEI_PRI, 1);
} else {
return __pri_new_tei(fd, nodetype, switchtype, NULL, io_read, io_write, userdata, Q921_TEI_GROUP, 1);
}
}
void *pri_get_userdata(struct pri *pri)
{
return pri ? pri->userdata : NULL;
@@ -433,32 +497,33 @@ char *pri_event2str(int id)
char *name;
} events[] = {
/* *INDENT-OFF* */
{ PRI_EVENT_DCHAN_UP, "D-Channel Up" },
{ PRI_EVENT_DCHAN_DOWN, "D-channel Down" },
{ PRI_EVENT_RESTART, "Restart channel" },
{ PRI_EVENT_CONFIG_ERR, "Configuration Error" },
{ PRI_EVENT_RING, "Ring" },
{ PRI_EVENT_HANGUP, "Hangup" },
{ PRI_EVENT_RINGING, "Ringing" },
{ PRI_EVENT_ANSWER, "Answer" },
{ PRI_EVENT_HANGUP_ACK, "Hangup ACK" },
{ PRI_EVENT_RESTART_ACK, "Restart ACK" },
{ PRI_EVENT_FACILITY, "Facility" },
{ PRI_EVENT_INFO_RECEIVED, "Info Received" },
{ PRI_EVENT_PROCEEDING, "Proceeding" },
{ PRI_EVENT_SETUP_ACK, "Setup ACK" },
{ PRI_EVENT_HANGUP_REQ, "Hangup Req" },
{ PRI_EVENT_NOTIFY, "Notify" },
{ PRI_EVENT_PROGRESS, "Progress" },
{ PRI_EVENT_KEYPAD_DIGIT, "Keypad Digit" },
{ PRI_EVENT_SERVICE, "Service" },
{ PRI_EVENT_SERVICE_ACK, "Service ACK" },
{ PRI_EVENT_HOLD, "Hold" },
{ PRI_EVENT_HOLD_ACK, "Hold Ack" },
{ PRI_EVENT_HOLD_REJ, "Hold Rej" },
{ PRI_EVENT_RETRIEVE, "Retrieve" },
{ PRI_EVENT_RETRIEVE_ACK, "Retrieve ACK" },
{ PRI_EVENT_RETRIEVE_REJ, "Retrieve Rej" },
{ PRI_EVENT_DCHAN_UP, "PRI_EVENT_DCHAN_UP" },
{ PRI_EVENT_DCHAN_DOWN, "PRI_EVENT_DCHAN_DOWN" },
{ PRI_EVENT_RESTART, "PRI_EVENT_RESTART" },
{ PRI_EVENT_CONFIG_ERR, "PRI_EVENT_CONFIG_ERR" },
{ PRI_EVENT_RING, "PRI_EVENT_RING" },
{ PRI_EVENT_HANGUP, "PRI_EVENT_HANGUP" },
{ PRI_EVENT_RINGING, "PRI_EVENT_RINGING" },
{ PRI_EVENT_ANSWER, "PRI_EVENT_ANSWER" },
{ PRI_EVENT_HANGUP_ACK, "PRI_EVENT_HANGUP_ACK" },
{ PRI_EVENT_RESTART_ACK, "PRI_EVENT_RESTART_ACK" },
{ PRI_EVENT_FACILITY, "PRI_EVENT_FACILITY" },
{ PRI_EVENT_INFO_RECEIVED, "PRI_EVENT_INFO_RECEIVED" },
{ PRI_EVENT_PROCEEDING, "PRI_EVENT_PROCEEDING" },
{ PRI_EVENT_SETUP_ACK, "PRI_EVENT_SETUP_ACK" },
{ PRI_EVENT_HANGUP_REQ, "PRI_EVENT_HANGUP_REQ" },
{ PRI_EVENT_NOTIFY, "PRI_EVENT_NOTIFY" },
{ PRI_EVENT_PROGRESS, "PRI_EVENT_PROGRESS" },
{ PRI_EVENT_KEYPAD_DIGIT, "PRI_EVENT_KEYPAD_DIGIT" },
{ PRI_EVENT_SERVICE, "PRI_EVENT_SERVICE" },
{ PRI_EVENT_SERVICE_ACK, "PRI_EVENT_SERVICE_ACK" },
{ PRI_EVENT_HOLD, "PRI_EVENT_HOLD" },
{ PRI_EVENT_HOLD_ACK, "PRI_EVENT_HOLD_ACK" },
{ PRI_EVENT_HOLD_REJ, "PRI_EVENT_HOLD_REJ" },
{ PRI_EVENT_RETRIEVE, "PRI_EVENT_RETRIEVE" },
{ PRI_EVENT_RETRIEVE_ACK, "PRI_EVENT_RETRIEVE_ACK" },
{ PRI_EVENT_RETRIEVE_REJ, "PRI_EVENT_RETRIEVE_REJ" },
{ PRI_EVENT_CONNECT_ACK, "PRI_EVENT_CONNECT_ACK" },
/* *INDENT-ON* */
};
@@ -645,6 +710,22 @@ int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn)
return q931_connect(pri, call, channel, nonisdn);
}
int pri_connect_ack(struct pri *ctrl, q931_call *call, int channel)
{
if (!ctrl || !call) {
return -1;
}
return q931_connect_acknowledge(ctrl, call, channel);
}
void pri_connect_ack_enable(struct pri *ctrl, int enable)
{
if (ctrl) {
ctrl = PRI_MASTER(ctrl);
ctrl->manual_connect_ack = enable ? 1 : 0;
}
}
/*!
* \brief Copy the PRI party name to the Q.931 party name structure.
*
@@ -751,7 +832,7 @@ int pri_connected_line_update(struct pri *ctrl, q931_call *call, const struct pr
/* Update all subcalls with new local_id. */
if (call->outboundbroadcast && call->master_call == call) {
for (idx = 0; idx < Q931_MAX_TEI; ++idx) {
for (idx = 0; idx < ARRAY_LEN(call->subcalls); ++idx) {
subcall = call->subcalls[idx];
if (subcall) {
subcall->local_id = party_id;
@@ -818,7 +899,7 @@ int pri_redirecting_update(struct pri *ctrl, q931_call *call, const struct pri_p
* but update it just in case.
*/
if (call->outboundbroadcast && call->master_call == call) {
for (idx = 0; idx < Q931_MAX_TEI; ++idx) {
for (idx = 0; idx < ARRAY_LEN(call->subcalls); ++idx) {
subcall = call->subcalls[idx];
if (subcall) {
subcall->redirecting.to = call->redirecting.to;
@@ -903,6 +984,52 @@ int pri_redirecting_update(struct pri *ctrl, q931_call *call, const struct pri_p
return 0;
}
#if defined(STATUS_REQUEST_PLACE_HOLDER)
/*!
* \brief Poll/ping for the status of any "called" party.
*
* \param ctrl D channel controller.
* \param request_id The upper layer's ID number to match with the response in case
* there are several requests at the same time.
* \param req Setup request for "called" party to determine the status.
*
* \note
* There could be one or more PRI_SUBCMD_STATUS_REQ_RSP to the status request
* depending upon how many endpoints respond to the request.
* (This includes the timeout termination response.)
* \note
* Could be used to poll for the status of call-completion party B.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int pri_status_req(struct pri *ctrl, int request_id, const struct pri_sr *req)
{
return -1;
}
#endif /* defined(STATUS_REQUEST_PLACE_HOLDER) */
#if defined(STATUS_REQUEST_PLACE_HOLDER)
/*!
* \brief Response to a poll/ping request for status of any "called" party by libpri.
*
* \param ctrl D channel controller.
* \param invoke_id ID given by libpri when it requested the party status.
* \param status free(0)/busy(1)/incompatible(2)
*
* \note
* There could be zero, one, or more responses to the original
* status request depending upon how many endpoints respond to the request.
* \note
* Could be used to poll for the status of call-completion party B.
*
* \return Nothing
*/
void pri_status_req_rsp(struct pri *ctrl, int invoke_id, int status)
{
}
#endif /* defined(STATUS_REQUEST_PLACE_HOLDER) */
#if 0
/* deprecated routines, use pri_hangup */
int pri_release(struct pri *pri, q931_call *call, int cause)
@@ -922,47 +1049,64 @@ int pri_disconnect(struct pri *pri, q931_call *call, int cause)
int pri_channel_bridge(q931_call *call1, q931_call *call2)
{
struct q931_call *winner;
if (!call1 || !call2)
return -1;
/* Make sure we have compatible switchtypes */
if (call1->pri->switchtype != call2->pri->switchtype)
winner = q931_find_winning_call(call1);
if (!winner) {
/* Cannot transfer: Call 1 does not have a winner yet. */
return -1;
}
call1 = winner;
/* Check for bearer capability */
if (call1->transcapability != call2->transcapability)
winner = q931_find_winning_call(call2);
if (!winner) {
/* Cannot transfer: Call 2 does not have a winner yet. */
return -1;
}
call2 = winner;
/* Check to see if we're on the same PRI */
if (call1->pri != call2->pri)
if (call1->pri != call2->pri) {
return -1;
switch (call1->pri->switchtype) {
case PRI_SWITCH_NI2:
case PRI_SWITCH_LUCENT5E:
case PRI_SWITCH_ATT4ESS:
if (eect_initiate_transfer(call1->pri, call1, call2))
return -1;
else
return 0;
break;
case PRI_SWITCH_DMS100:
if (rlt_initiate_transfer(call1->pri, call1, call2))
return -1;
else
return 0;
break;
case PRI_SWITCH_QSIG:
call1->bridged_call = call2;
call2->bridged_call = call1;
if (anfpr_initiate_transfer(call1->pri, call1, call2))
return -1;
else
return 0;
break;
default:
return -1;
}
/* Check for bearer capability */
if (call1->bc.transcapability != call2->bc.transcapability)
return -1;
switch (call1->pri->switchtype) {
case PRI_SWITCH_NI2:
case PRI_SWITCH_LUCENT5E:
case PRI_SWITCH_ATT4ESS:
if (eect_initiate_transfer(call1->pri, call1, call2)) {
return -1;
}
break;
case PRI_SWITCH_DMS100:
if (rlt_initiate_transfer(call1->pri, call1, call2)) {
return -1;
}
break;
case PRI_SWITCH_QSIG:
call1->bridged_call = call2;
call2->bridged_call = call1;
if (anfpr_initiate_transfer(call1->pri, call1, call2)) {
return -1;
}
break;
case PRI_SWITCH_EUROISDN_E1:
case PRI_SWITCH_EUROISDN_T1:
if (etsi_initiate_transfer(call1->pri, call1, call2)) {
return -1;
}
break;
default:
return -1;
}
return 0;
}
void pri_hangup_fix_enable(struct pri *ctrl, int enable)
@@ -1018,29 +1162,9 @@ void pri_dump_event(struct pri *pri, pri_event *e)
if (!pri || !e)
return;
pri_message(pri, "Event type: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
switch(e->gen.e) {
case PRI_EVENT_DCHAN_UP:
case PRI_EVENT_DCHAN_DOWN:
break;
case PRI_EVENT_CONFIG_ERR:
pri_message(pri, "Error: %s", e->err.err);
break;
case PRI_EVENT_RESTART:
pri_message(pri, "Restart on channel %d\n", e->restart.channel);
case PRI_EVENT_RING:
pri_message(pri, "Calling number: %s (%s, %s)\n", e->ring.callingnum, pri_plan2str(e->ring.callingplan), pri_pres2str(e->ring.callingpres));
pri_message(pri, "Called number: %s (%s)\n", e->ring.callednum, pri_plan2str(e->ring.calledplan));
pri_message(pri, "Channel: %d (%s) Reference number: %d\n", e->ring.channel, e->ring.flexible ? "Flexible" : "Not Flexible", e->ring.cref);
break;
case PRI_EVENT_HANGUP:
pri_message(pri, "Hangup, reference number: %d, reason: %s\n", e->hangup.cref, pri_cause2str(e->hangup.cause));
break;
default:
pri_message(pri, "Don't know how to dump events of type %d\n", e->gen.e);
}
}
static void pri_sr_init(struct pri_sr *req)
void pri_sr_init(struct pri_sr *req)
{
memset(req, 0, sizeof(struct pri_sr));
q931_party_redirecting_init(&req->redirecting);
@@ -1503,6 +1627,14 @@ void pri_sr_set_keypad_digits(struct pri_sr *sr, const char *keypad_digits)
sr->keypad_digits = keypad_digits;
}
void pri_transfer_enable(struct pri *ctrl, int enable)
{
if (ctrl) {
ctrl = PRI_MASTER(ctrl);
ctrl->transfer_support = enable ? 1 : 0;
}
}
void pri_hold_enable(struct pri *ctrl, int enable)
{
if (ctrl) {
@@ -1618,3 +1750,35 @@ int pri_reroute_call(struct pri *ctrl, q931_call *call, const struct pri_party_i
return send_reroute_request(ctrl, call, caller_id, &reroute, subscription_option);
}
void pri_cc_enable(struct pri *ctrl, int enable)
{
if (ctrl) {
ctrl = PRI_MASTER(ctrl);
ctrl->cc_support = enable ? 1 : 0;
}
}
void pri_cc_recall_mode(struct pri *ctrl, int mode)
{
if (ctrl) {
ctrl = PRI_MASTER(ctrl);
ctrl->cc.option.recall_mode = mode ? 1 : 0;
}
}
void pri_cc_retain_signaling_req(struct pri *ctrl, int signaling_retention)
{
if (ctrl && 0 <= signaling_retention && signaling_retention < 3) {
ctrl = PRI_MASTER(ctrl);
ctrl->cc.option.signaling_retention_req = signaling_retention;
}
}
void pri_cc_retain_signaling_rsp(struct pri *ctrl, int signaling_retention)
{
if (ctrl) {
ctrl = PRI_MASTER(ctrl);
ctrl->cc.option.signaling_retention_rsp = signaling_retention ? 1 : 0;
}
}

1765
pri_aoc.c Normal file

File diff suppressed because it is too large Load Diff

7872
pri_cc.c Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -30,13 +30,7 @@
#ifndef _PRI_FACILITY_H
#define _PRI_FACILITY_H
#include "pri_q931.h"
/* Forward declare some structs */
struct fac_extension_header;
struct rose_msg_invoke;
struct rose_msg_result;
struct rose_msg_error;
struct rose_msg_reject;
#include "rose.h"
/* Protocol Profile field */
#define Q932_PROTOCOL_MASK 0x1F
@@ -75,7 +69,7 @@ struct rose_msg_reject;
/*! Reasons an APDU callback is called. */
enum APDU_CALLBACK_REASON {
/*!
* \brief Send setup error. Abort and cleanup.
* \brief Transmit facility ie setup error. Abort and cleanup.
* \note The message may or may not actually get sent.
* \note The callback cannot generate an event subcmd.
* \note The callback should not send messages. Out of order messages will result.
@@ -114,10 +108,15 @@ enum APDU_CALLBACK_REASON {
APDU_CALLBACK_REASON_MSG_REJECT,
};
union apdu_msg_data {
const struct rose_msg_result *result;
const struct rose_msg_error *error;
const struct rose_msg_reject *reject;
struct apdu_msg_data {
/*! Decoded response message contents. */
union {
const struct rose_msg_result *result;
const struct rose_msg_error *error;
const struct rose_msg_reject *reject;
} response;
/*! Q.931 message type the response came in with. */
int type;
};
union apdu_callback_param {
@@ -126,15 +125,24 @@ union apdu_callback_param {
char pad[8];
};
/* So calls to pri_call_apdu_find() will not find an aliased event. */
#define APDU_INVALID_INVOKE_ID 0x10000
#define APDU_TIMEOUT_MSGS_ONLY -1
struct apdu_callback_data {
/*! APDU invoke id to match with any response messages. (Result/Error/Reject) */
int invoke_id;
/*!
* \brief Time to wait for responses to APDU in ms.
* \note Set to 0 if send the message only.
* \note Set to less than 0 for PRI_TIMER_T_RESPONSE time.
* \note Set to APDU_TIMEOUT_MSGS_ONLY to "timeout" with the message_type list only.
*/
int timeout_time;
/*! Number of Q.931 messages the APDU can "timeout" on. */
unsigned num_messages;
/*! Q.931 message list to "timeout" on. */
int message_type[5];
/*!
* \brief APDU callback function.
*
@@ -149,7 +157,7 @@ struct apdu_callback_data {
*
* \return TRUE if no more responses are expected.
*/
int (*callback)(enum APDU_CALLBACK_REASON reason, struct pri *ctrl, struct q931_call *call, struct apdu_event *apdu, const union apdu_msg_data *msg);
int (*callback)(enum APDU_CALLBACK_REASON reason, struct pri *ctrl, struct q931_call *call, struct apdu_event *apdu, const struct apdu_msg_data *msg);
/*! \brief Sender data for the callback function to identify the particular APDU. */
union apdu_callback_param user;
};
@@ -173,6 +181,29 @@ struct apdu_event {
unsigned char apdu[255];
};
void rose_copy_number_to_q931(struct pri *ctrl, struct q931_party_number *q931_number, const struct rosePartyNumber *rose_number);
void rose_copy_subaddress_to_q931(struct pri *ctrl, struct q931_party_subaddress *q931_subaddress, const struct rosePartySubaddress *rose_subaddress);
void rose_copy_address_to_q931(struct pri *ctrl, struct q931_party_address *q931_address, const struct roseAddress *rose_address);
void rose_copy_address_to_id_q931(struct pri *ctrl, struct q931_party_id *q931_address, const struct roseAddress *rose_address);
void rose_copy_presented_number_screened_to_q931(struct pri *ctrl, struct q931_party_number *q931_number, const struct rosePresentedNumberScreened *rose_presented);
void rose_copy_presented_number_unscreened_to_q931(struct pri *ctrl, struct q931_party_number *q931_number, const struct rosePresentedNumberUnscreened *rose_presented);
void rose_copy_presented_address_screened_to_id_q931(struct pri *ctrl, struct q931_party_id *q931_address, const struct rosePresentedAddressScreened *rose_presented);
void rose_copy_name_to_q931(struct pri *ctrl, struct q931_party_name *qsig_name, const struct roseQsigName *rose_name);
void q931_copy_number_to_rose(struct pri *ctrl, struct rosePartyNumber *rose_number, const struct q931_party_number *q931_number);
void q931_copy_subaddress_to_rose(struct pri *ctrl, struct rosePartySubaddress *rose_subaddress, const struct q931_party_subaddress *q931_subaddress);
void q931_copy_address_to_rose(struct pri *ctrl, struct roseAddress *rose_address, const struct q931_party_address *q931_address);
void q931_copy_id_address_to_rose(struct pri *ctrl, struct roseAddress *rose_address, const struct q931_party_id *q931_address);
void q931_copy_presented_number_screened_to_rose(struct pri *ctrl, struct rosePresentedNumberScreened *rose_presented, const struct q931_party_number *q931_number);
void q931_copy_presented_number_unscreened_to_rose(struct pri *ctrl, struct rosePresentedNumberUnscreened *rose_presented, const struct q931_party_number *q931_number);
void q931_copy_presented_id_address_screened_to_rose(struct pri *ctrl, struct rosePresentedAddressScreened *rose_presented, const struct q931_party_id *q931_address);
void q931_copy_name_to_rose(struct pri *ctrl, struct roseQsigName *rose_name, const struct q931_party_name *qsig_name);
int rose_error_msg_encode(struct pri *ctrl, q931_call *call, int msgtype, int invoke_id, enum rose_error_code code);
int send_facility_error(struct pri *ctrl, q931_call *call, int invoke_id, enum rose_error_code code);
int rose_result_ok_encode(struct pri *ctrl, q931_call *call, int msgtype, int invoke_id);
int send_facility_result_ok(struct pri *ctrl, q931_call *call, int invoke_id);
/* Queues an MWI apdu on a the given call */
int mwi_message_send(struct pri *pri, q931_call *call, struct pri_sr *req, int activate);
@@ -181,12 +212,14 @@ int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2);
int rlt_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2);
int qsig_cf_callrerouting(struct pri *pri, q931_call *c, const char* dest, const char* original, const char* reason);
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);
/* starts a QSIG Path Replacement */
int anfpr_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2);
int etsi_initiate_transfer(struct pri *ctrl, q931_call *call_1, q931_call *call_2);
int qsig_cf_callrerouting(struct pri *pri, q931_call *c, const char* dest, const char* original, const char* reason);
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_diverting_leg_information1_encode(struct pri *pri, q931_call *call);
@@ -197,6 +230,8 @@ int rose_called_name_encode(struct pri *pri, q931_call *call, int messagetype);
int pri_call_apdu_queue(q931_call *call, int messagetype, const unsigned char *apdu, int apdu_len, struct apdu_callback_data *response);
void pri_call_apdu_queue_cleanup(q931_call *call);
struct apdu_event *pri_call_apdu_find(struct q931_call *call, int invoke_id);
int pri_call_apdu_extract(struct q931_call *call, struct apdu_event *extract);
void pri_call_apdu_delete(struct q931_call *call, struct apdu_event *doomed);
/* Adds the "standard" APDUs to a call */
@@ -209,4 +244,20 @@ void rose_handle_result(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
void rose_handle_error(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, const struct fac_extension_header *header, const struct rose_msg_error *error);
void rose_handle_reject(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, const struct fac_extension_header *header, const struct rose_msg_reject *reject);
int pri_cc_interrogate_rsp(struct pri *ctrl, q931_call *call, const struct rose_msg_invoke *invoke);
void pri_cc_ptmp_request(struct pri *ctrl, q931_call *call, const struct rose_msg_invoke *invoke);
void pri_cc_ptp_request(struct pri *ctrl, q931_call *call, int msgtype, const struct rose_msg_invoke *invoke);
void pri_cc_qsig_request(struct pri *ctrl, q931_call *call, int msgtype, const struct rose_msg_invoke *invoke);
void pri_cc_qsig_cancel(struct pri *ctrl, q931_call *call, int msgtype, const struct rose_msg_invoke *invoke);
void pri_cc_qsig_exec_possible(struct pri *ctrl, q931_call *call, int msgtype, const struct rose_msg_invoke *invoke);
int aoc_charging_request_send(struct pri *ctrl, q931_call *c, enum PRI_AOC_REQUEST aoc_request_flag);
void aoc_etsi_aoc_request(struct pri *ctrl, q931_call *call, const struct rose_msg_invoke *invoke);
void aoc_etsi_aoc_s_currency(struct pri *ctrl, const struct rose_msg_invoke *invoke);
void aoc_etsi_aoc_s_special_arrangement(struct pri *ctrl, const struct rose_msg_invoke *invoke);
void aoc_etsi_aoc_d_currency(struct pri *ctrl, const struct rose_msg_invoke *invoke);
void aoc_etsi_aoc_d_charging_unit(struct pri *ctrl, const struct rose_msg_invoke *invoke);
void aoc_etsi_aoc_e_currency(struct pri *ctrl, q931_call *call, const struct rose_msg_invoke *invoke);
void aoc_etsi_aoc_e_charging_unit(struct pri *ctrl, q931_call *call, const struct rose_msg_invoke *invoke);
#endif /* _PRI_FACILITY_H */

View File

@@ -42,6 +42,7 @@
/* Forward declare some structs */
struct apdu_event;
struct pri_cc_record;
struct pri_sched {
struct timeval when;
@@ -49,8 +50,12 @@ struct pri_sched {
void *data;
};
/*! Maximum number of scheduled events active at the same time. */
#define MAX_SCHED 128
/*
* libpri needs to be able to allocate B channels to support Q.SIG path reservation.
* Until that happens, path reservation is not possible. Fortunately,
* path reservation is optional with a fallback to what we can implement.
*/
//#define QSIG_PATH_RESERVATION_SUPPORT 1
/*! Maximum number of facility ie's to handle per incoming message. */
#define MAX_FACILITY_IES 8
@@ -73,7 +78,14 @@ struct pri {
struct pri_msg_line *msg_line;
struct pri *subchannel; /* Sub-channel if appropriate */
struct pri *master; /* Master channel if appropriate */
struct pri_sched pri_sched[MAX_SCHED]; /* Scheduled events */
struct {
/*! Dynamically allocated array of timers that can grow as needed. */
struct pri_sched *timer;
/*! Numer of timer slots in the allocated array of timers. */
unsigned num_slots;
/*! Maximum timer slots currently needed. */
unsigned max_used;
} sched;
int debug; /* Debug stuff */
int state; /* State of D-channel */
int switchtype; /* Switch type */
@@ -93,6 +105,11 @@ struct pri {
unsigned int hold_support:1;/* TRUE if upper layer supports call hold. */
unsigned int deflection_support:1;/* TRUE if upper layer supports call deflection/rerouting. */
unsigned int hangup_fix_enabled:1;/* TRUE if should follow Q.931 Section 5.3.2 instead of blindly sending RELEASE_COMPLETE for certain causes */
unsigned int cc_support:1;/* TRUE if upper layer supports call completion. */
unsigned int transfer_support:1;/* TRUE if the upper layer supports ECT */
unsigned int aoc_support:1;/* TRUE if can send AOC events to the upper layer. */
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;
@@ -156,6 +173,31 @@ struct pri {
short last_invoke; /* Last ROSE invoke ID (Valid in master record only) */
/*! Call completion (Valid in master record only) */
struct {
/*! Active CC records */
struct pri_cc_record *pool;
/*! Last CC record id allocated. */
unsigned short last_record_id;
/*! Last CC PTMP reference id allocated. (0-127) */
unsigned char last_reference_id;
/*! Last CC PTMP linkage id allocated. (0-127) */
unsigned char last_linkage_id;
/*! Configured CC options. */
struct {
/*! PTMP recall mode: globalRecall(0), specificRecall(1) */
unsigned char recall_mode;
/*! Q.SIG Request signaling link retention: release(0), retain(1), do-not-care(2) */
unsigned char signaling_retention_req;
/*! Q.SIG Response request signaling link retention: release(0), retain(1) */
unsigned char signaling_retention_rsp;
#if defined(QSIG_PATH_RESERVATION_SUPPORT)
/*! Q.SIG TRUE if response request can support path reservation. */
unsigned char allow_path_reservation;
#endif /* defined(QSIG_PATH_RESERVATION_SUPPORT) */
} option;
} cc;
/*! For delayed processing of facility ie's. */
struct {
/*! Array of facility ie locations in the current received message. */
@@ -324,6 +366,7 @@ struct pri_sr {
const char *keypad_digits;
int transferable;
int reversecharge;
int aoc_charging_request;
};
/* Internal switch types */
@@ -370,6 +413,38 @@ enum Q931_HOLD_STATE {
Q931_HOLD_STATE_RETRIEVE_IND,
};
/* Only save the first of each BC, HLC, and LLC from the initial SETUP. */
#define CC_SAVED_IE_BC (1 << 0) /*!< BC has already been saved. */
#define CC_SAVED_IE_HLC (1 << 1) /*!< HLC has already been saved. */
#define CC_SAVED_IE_LLC (1 << 2) /*!< LLC has already been saved. */
/*! Saved ie contents for BC, HLC, and LLC. (Only the first of each is saved.) */
struct q931_saved_ie_contents {
/*! Length of saved ie contents. */
unsigned char length;
/*! Saved ie contents data. */
unsigned char data[
/* Bearer Capability has a max length of 12. */
12
/* High Layer Compatibility has a max length of 5. */
+ 5
/* Low Layer Compatibility has a max length of 18. */
+ 18
/* Room for null terminator just in case. */
+ 1];
};
/*! Digested BC parameters. */
struct decoded_bc {
int transcapability;
int transmoderate;
int transmultiple;
int userl1;
int userl2;
int userl3;
int rateadaption;
};
/* q931_call datastructure */
struct q931_call {
struct pri *pri; /* PRI */
@@ -394,20 +469,21 @@ struct q931_call {
int ri; /* Restart Indicator (Restart Indicator IE) */
/* Bearer Capability */
int transcapability;
int transmoderate;
int transmultiple;
int userl1;
int userl2;
int userl3;
int rateadaption;
/*! Bearer Capability */
struct decoded_bc bc;
/*!
* \brief TRUE if the call is a Call Independent Signalling connection.
* \note The call has no B channel associated with it. (Just signalling)
*/
int cis_call;
/*!
* \brief TRUE if we have recognized a use for this CIS call.
* \note An incoming CIS call will be immediately disconnected if not set.
* This is a safeguard against unhandled incoming CIS calls to protect the
* call reference pool.
*/
int cis_recognized;
/*! \brief TRUE if we will auto disconnect the cis_call we originated. */
int cis_auto_disconnect;
@@ -458,6 +534,8 @@ struct q931_call {
* (Caller-ID for answered or connected-line for originated calls.)
*/
struct q931_party_id remote_id;
/*! \brief Automatic Number Identification (ANI) */
struct q931_party_number ani;
/*!
* \brief Staging place for the Q.931 redirection number ie.
@@ -506,6 +584,11 @@ struct q931_call {
int transferable; /* RLT call is transferable */
unsigned int rlt_call_id; /* RLT call id */
/*! ETSI Explicit Call Transfer link id. */
int link_id;
/*! TRUE if link_id is valid. */
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) */
@@ -530,6 +613,264 @@ struct q931_call {
/* These valid in master call only */
struct q931_call *subcalls[Q931_MAX_TEI];
int pri_winner;
/* Call completion */
struct {
/*!
* \brief CC record associated with this call.
* \note
* CC signaling link or original call when cc-available indicated.
*/
struct pri_cc_record *record;
/*! Original calling party. */
struct q931_party_id party_a;
/*! Saved BC, HLC, and LLC from initial SETUP */
struct q931_saved_ie_contents saved_ie_contents;
/*! Only save the first of each BC, HLC, and LLC from the initial SETUP. */
unsigned char saved_ie_flags;
/*! TRUE if call needs to be hung up. */
unsigned char hangup_call;
/*! TRUE if we originated this call. */
unsigned char originated;
/*! TRUE if outgoing call was already redirected. */
unsigned char initially_redirected;
} cc;
/* AOC charge requesting on Setup */
int aoc_charging_request;
};
enum CC_STATES {
/*! CC is not active. */
CC_STATE_IDLE,
// /*! CC has recorded call information in anticipation of CC availability. */
// CC_STATE_RECORD_RETENTION,
/*! CC is available and waiting on ALERTING or DISCONNECT to go out. */
CC_STATE_PENDING_AVAILABLE,
/*! CC is available and waiting on possible CC request. */
CC_STATE_AVAILABLE,
/*! CC is requested to be activated and waiting on party B to acknowledge. */
CC_STATE_REQUESTED,
/*! CC is activated and waiting for party B to become available. */
CC_STATE_ACTIVATED,
/*! CC party B is available and waiting for status of party A. */
CC_STATE_B_AVAILABLE,
/*! CC is suspended because party A is not available. (Monitor party A.) */
CC_STATE_SUSPENDED,
/*! CC is waiting for party A to initiate CC callback. */
CC_STATE_WAIT_CALLBACK,
/*! CC callback in progress. */
CC_STATE_CALLBACK,
/*! CC is waiting for signaling link to be cleared before destruction. */
CC_STATE_WAIT_DESTRUCTION,
/*! Number of CC states. Must be last in enum. */
CC_STATE_NUM
};
enum CC_EVENTS {
/*! CC is available for the current call. */
CC_EVENT_AVAILABLE,
/*! Requesting CC activation. */
CC_EVENT_CC_REQUEST,
/*! Requesting CC activation accepted. */
CC_EVENT_CC_REQUEST_ACCEPT,
/*! Requesting CC activation failed (error/reject received). */
CC_EVENT_CC_REQUEST_FAIL,
/*! CC party B is available, party A is considered free. */
CC_EVENT_REMOTE_USER_FREE,
/*! CC party B is available, party A is busy or CCBS busy. */
CC_EVENT_B_FREE,
/*! Someone else responded to the CC recall. */
CC_EVENT_STOP_ALERTING,
/*! CC poll/prompt for party A status. */
CC_EVENT_A_STATUS,
/*! CC party A is free/available for recall. */
CC_EVENT_A_FREE,
/*! CC party A is busy/not-available for recall. */
CC_EVENT_A_BUSY,
/*! Suspend monitoring party B because party A is busy. */
CC_EVENT_SUSPEND,
/*! Resume monitoring party B because party A is now available. */
CC_EVENT_RESUME,
/*! This is the CC recall call attempt. */
CC_EVENT_RECALL,
/*! Link request to cancel/deactivate CC received. */
CC_EVENT_LINK_CANCEL,
/*! Tear down CC request from upper layer. */
CC_EVENT_CANCEL,
/*! 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. */
CC_EVENT_HANGUP_SIGNALING,
/*! Sent ALERTING message. */
CC_EVENT_MSG_ALERTING,
/*! Sent DISCONNECT message. */
CC_EVENT_MSG_DISCONNECT,
/*! Sent RELEASE message. */
CC_EVENT_MSG_RELEASE,
/*! Sent RELEASE_COMPLETE message. */
CC_EVENT_MSG_RELEASE_COMPLETE,
/*! T_ACTIVATE timer timed out. */
CC_EVENT_TIMEOUT_T_ACTIVATE,
#if 0
/*! T_DEACTIVATE timer timed out. */
CC_EVENT_TIMEOUT_T_DEACTIVATE,
/*! T_INTERROGATE timer timed out. */
CC_EVENT_TIMEOUT_T_INTERROGATE,
#endif
/*! T_RETENTION timer timed out. */
CC_EVENT_TIMEOUT_T_RETENTION,
/*! T-STATUS timer equivalent for CC user A status timed out. */
CC_EVENT_TIMEOUT_T_CCBS1,
/*! Timeout for valid party A status. */
CC_EVENT_TIMEOUT_EXTENDED_T_CCBS1,
/*! Max time the CCBS/CCNR service will be active. */
CC_EVENT_TIMEOUT_T_SUPERVISION,
/*! Max time to wait for user A to respond to user B availability. */
CC_EVENT_TIMEOUT_T_RECALL,
};
enum CC_PARTY_A_AVAILABILITY {
CC_PARTY_A_AVAILABILITY_INVALID,
CC_PARTY_A_AVAILABILITY_BUSY,
CC_PARTY_A_AVAILABILITY_FREE,
};
/* Invalid PTMP call completion reference and linkage id value. */
#define CC_PTMP_INVALID_ID 0xFF
/*! \brief Call-completion record */
struct pri_cc_record {
/*! Next call-completion record in the list */
struct pri_cc_record *next;
/*! Master D channel control structure. */
struct pri *master;
/*! Original call that is offered CC availability. (NULL if no longer exists.) */
struct q931_call *original_call;
/*!
* \brief Associated signaling link. (NULL if not established.)
* \note
* PTMP - Broadcast dummy call reference call.
* (If needed, the TE side could use this pointer to locate its specific
* dummy call reference call.)
* \note
* PTP - REGISTER signaling link.
* \note
* Q.SIG - SETUP signaling link.
*/
struct q931_call *signaling;
/*! Call-completion record id (0 - 65535) */
long record_id;
/*! Call-completion state */
enum CC_STATES state;
/*! Original calling party. */
struct q931_party_id party_a;
/*! Original called party. */
struct q931_party_address party_b;
/*! Saved BC, HLC, and LLC from initial SETUP */
struct q931_saved_ie_contents saved_ie_contents;
/*! Saved decoded BC */
struct decoded_bc bc;
/*! FSM parameters. */
union {
/*! PTMP FSM parameters. */
struct {
/*! Extended T_CCBS1 timer id for CCBSStatusRequest handling. */
int extended_t_ccbs1;
/*! Invoke id for the CCBSStatusRequest message to find if T_CCBS1 still running. */
int t_ccbs1_invoke_id;
/*! Number of times party A status request got no responses. */
int party_a_status_count;
/*! Accumulating party A availability status */
enum CC_PARTY_A_AVAILABILITY party_a_status_acc;
} ptmp;
/*! PTP FSM parameters. */
struct {
} ptp;
struct {
/*! Q.931 message type the current message event came in on. */
int msgtype;
} qsig;
} fsm;
/*! Received message parameters of interest. */
union {
/*! cc-request error/reject response */
struct {
/*! enum APDU_CALLBACK_REASON reason */
int reason;
/*! MSG_ERROR/MSG_REJECT fail code. */
int code;
} cc_req_rsp;
} msg;
/*! Party A availability status */
enum CC_PARTY_A_AVAILABILITY party_a_status;
/*! Indirect timer id to abort indirect action events. */
int t_indirect;
/*!
* \brief PTMP T_RETENTION timer id.
* \note
* This timer is used by all CC agents to implement
* the Asterisk CC core offer timer.
*/
int t_retention;
/*!
* \brief CC service supervision timer.
*
* \details
* This timer is one of the following timer id's depending upon
* switch type and CC mode:
* PTMP - T_CCBS2/T_CCNR2,
* PTP - T_CCBS5/T_CCNR5/T_CCBS6/T_CCNR6,
* Q.SIG - QSIG_CCBS_T2/QSIG_CCNR_T2
*/
int t_supervision;
/*!
* \brief Party A response to B availability for recall timer.
* \details
* This timer is one of the following timer id's:
* PTMP - T_CCBS3
* Q.SIG - QSIG_CC_T3
*/
int t_recall;
/*! Invoke id for the cc-request message to find if T_ACTIVATE/QSIG_CC_T1 still running. */
int t_activate_invoke_id;
/*! Pending response information. */
struct {
/*!
* \brief Send response on this signaling link.
* \note Used by PTMP for CCBSRequest/CCNRRequest/CCBSCall responses.
* \note Used by Q.SIG for ccRingout responses.
*/
struct q931_call *signaling;
/*! Invoke operation code */
int invoke_operation;
/*! Invoke id to use in the pending response. */
short invoke_id;
} response;
/*! TRUE if the call-completion FSM has completed and this record needs to be destroyed. */
unsigned char fsm_complete;
/*! TRUE if we are a call completion agent. */
unsigned char is_agent;
/*! TRUE if active cc mode is CCNR. */
unsigned char is_ccnr;
/*! PTMP pre-activation reference id. (0-127) */
unsigned char call_linkage_id;
/*! PTMP active CCBS reference id. (0-127) */
unsigned char ccbs_reference_id;
/*! Negotiated options */
struct {
/*! PTMP recall mode: globalRecall(0), specificRecall(1) */
unsigned char recall_mode;
/*! TRUE if negotiated for Q.SIG signaling link to be retained. */
unsigned char retain_signaling_link;
#if defined(QSIG_PATH_RESERVATION_SUPPORT)
/*! Q.SIG TRUE if can do path reservation. */
unsigned char do_path_reservation;
#endif /* defined(QSIG_PATH_RESERVATION_SUPPORT) */
} option;
};
/*! D channel control structure with associated dummy call reference record. */
@@ -558,6 +899,8 @@ void __pri_free_tei(struct pri *p);
void q931_init_call_record(struct pri *ctrl, struct q931_call *call, int cr);
void pri_sr_init(struct pri_sr *req);
void q931_party_name_init(struct q931_party_name *name);
void q931_party_number_init(struct q931_party_number *number);
void q931_party_subaddress_init(struct q931_party_subaddress *subaddr);
@@ -565,20 +908,32 @@ void q931_party_address_init(struct q931_party_address *address);
void q931_party_id_init(struct q931_party_id *id);
void q931_party_redirecting_init(struct q931_party_redirecting *redirecting);
static inline void q931_party_address_to_id(struct q931_party_id *id, struct q931_party_address *address)
static inline void q931_party_address_to_id(struct q931_party_id *id, const struct q931_party_address *address)
{
id->number = address->number;
id->subaddress = address->subaddress;
}
static inline void q931_party_id_to_address(struct q931_party_address *address, const struct q931_party_id *id)
{
address->number = id->number;
address->subaddress = id->subaddress;
}
int q931_party_name_cmp(const struct q931_party_name *left, const struct q931_party_name *right);
int q931_party_number_cmp(const struct q931_party_number *left, const struct q931_party_number *right);
int q931_party_subaddress_cmp(const struct q931_party_subaddress *left, const struct q931_party_subaddress *right);
int q931_party_address_cmp(const struct q931_party_address *left, const struct q931_party_address *right);
int q931_party_id_cmp(const struct q931_party_id *left, const struct q931_party_id *right);
int q931_party_id_cmp_address(const struct q931_party_id *left, const struct q931_party_id *right);
int q931_cmp_party_id_to_address(const struct q931_party_id *id, const struct q931_party_address *address);
void q931_party_id_copy_to_address(struct q931_party_address *address, const struct q931_party_id *id);
void q931_party_name_copy_to_pri(struct pri_party_name *pri_name, const struct q931_party_name *q931_name);
void q931_party_number_copy_to_pri(struct pri_party_number *pri_number, const struct q931_party_number *q931_number);
void q931_party_subaddress_copy_to_pri(struct pri_party_subaddress *pri_subaddress, const struct q931_party_subaddress *q931_subaddress);
void q931_party_address_copy_to_pri(struct pri_party_address *pri_address, const struct q931_party_address *q931_address);
void q931_party_id_copy_to_pri(struct pri_party_id *pri_id, const struct q931_party_id *q931_id);
void q931_party_redirecting_copy_to_pri(struct pri_party_redirecting *pri_redirecting, const struct q931_party_redirecting *q931_redirecting);
@@ -593,11 +948,24 @@ int q931_party_id_presentation(const struct q931_party_id *id);
const char *q931_call_state_str(enum Q931_CALL_STATE callstate);
const char *msg2str(int msg);
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);
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);
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);
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.
*
@@ -731,4 +1099,10 @@ static inline int q931_is_dummy_call(const 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;
}
#endif

View File

@@ -82,6 +82,9 @@ typedef struct q931_ie {
/* Q.931 / National ISDN Message Types */
/*! Send this facility APDU on the next message to go out. */
#define Q931_ANY_MESSAGE -1
/* Call Establishment Messages */
#define Q931_ALERTING 0x01
#define Q931_CALL_PROCEEDING 0x02
@@ -106,6 +109,7 @@ typedef struct q931_ie {
#define Q931_CONGESTION_CONTROL 0x79
#define Q931_INFORMATION 0x7b
#define Q931_FACILITY 0x62
#define Q931_REGISTER 0x64 /* Q.932 */
#define Q931_NOTIFY 0x6e
/* Call Management Messages */
@@ -471,6 +475,7 @@ extern int q931_information(struct pri *pri, q931_call *call, char digit);
extern int q931_keypad_facility(struct pri *pri, q931_call *call, const char *digits);
extern int q931_connect(struct pri *pri, q931_call *call, int channel, int nonisdn);
int q931_connect_acknowledge(struct pri *ctrl, q931_call *call, int channel);
extern int q931_release(struct pri *pri, q931_call *call, int cause);
@@ -490,6 +495,9 @@ struct q931_call *q931_find_call(struct pri *ctrl, int cr);
struct q931_call *q931_new_call(struct pri *pri);
extern int q931_setup(struct pri *pri, q931_call *c, struct pri_sr *req);
int q931_register(struct pri *ctrl, q931_call *call);
void q931_dump(struct pri *ctrl, int tei, q931_h *h, int len, int txrx);
void q931_destroycall(struct pri *pri, q931_call *c);

View File

@@ -28,16 +28,73 @@
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "libpri.h"
#include "pri_internal.h"
/*! 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.
*/
#define SCHED_EVENTS_MAX 8192
/*! \brief The maximum number of timers that were active at once. */
static int maxsched = 0;
static unsigned maxsched = 0;
/* Scheduler routines */
/*!
* \internal
* \brief Increase the number of scheduler timer slots available.
*
* \param ctrl D channel controller.
*
* \retval 0 on success.
* \retval -1 on error.
*/
static int pri_schedule_grow(struct pri *ctrl)
{
unsigned num_slots;
struct pri_sched *timers;
/* Determine how many slots in the new timer table. */
if (ctrl->sched.num_slots) {
if (SCHED_EVENTS_MAX <= ctrl->sched.num_slots) {
/* Cannot grow the timer table any more. */
return -1;
}
num_slots = ctrl->sched.num_slots * 2;
if (SCHED_EVENTS_MAX < num_slots) {
num_slots = SCHED_EVENTS_MAX;
}
} else {
num_slots = SCHED_EVENTS_INITIAL;
}
/* Get and initialize the new timer table. */
timers = calloc(num_slots, sizeof(struct pri_sched));
if (!timers) {
/* Could not get a new timer table. */
return -1;
}
if (ctrl->sched.timer) {
/* Copy over the old timer table. */
memcpy(timers, ctrl->sched.timer,
ctrl->sched.num_slots * sizeof(struct pri_sched));
free(ctrl->sched.timer);
}
/* Put the new timer table in place. */
ctrl->sched.timer = timers;
ctrl->sched.num_slots = num_slots;
return 0;
}
/*!
* \brief Start a timer to schedule an event.
*
@@ -51,22 +108,26 @@ static int maxsched = 0;
*/
int pri_schedule_event(struct pri *ctrl, int ms, void (*function)(void *data), void *data)
{
int x;
unsigned max_used;
unsigned x;
struct timeval tv;
/* Scheduling runs on master channels only */
while (ctrl->master) {
ctrl = ctrl->master;
}
for (x = 0; x < MAX_SCHED; ++x) {
if (!ctrl->pri_sched[x].callback) {
ctrl = PRI_MASTER(ctrl);
max_used = ctrl->sched.max_used;
for (x = 0; x < max_used; ++x) {
if (!ctrl->sched.timer[x].callback) {
break;
}
}
if (x == MAX_SCHED) {
if (x == ctrl->sched.num_slots && pri_schedule_grow(ctrl)) {
pri_error(ctrl, "No more room in scheduler\n");
return 0;
}
if (ctrl->sched.max_used <= x) {
ctrl->sched.max_used = x + 1;
}
if (x >= maxsched) {
maxsched = x + 1;
}
@@ -77,9 +138,9 @@ int pri_schedule_event(struct pri *ctrl, int ms, void (*function)(void *data), v
tv.tv_usec -= 1000000;
tv.tv_sec += 1;
}
ctrl->pri_sched[x].when = tv;
ctrl->pri_sched[x].callback = function;
ctrl->pri_sched[x].data = data;
ctrl->sched.timer[x].when = tv;
ctrl->sched.timer[x].callback = function;
ctrl->sched.timer[x].data = data;
return x + 1;
}
@@ -93,20 +154,29 @@ int pri_schedule_event(struct pri *ctrl, int ms, void (*function)(void *data), v
struct timeval *pri_schedule_next(struct pri *ctrl)
{
struct timeval *closest = NULL;
int x;
unsigned x;
/* Scheduling runs on master channels only */
while (ctrl->master) {
ctrl = ctrl->master;
}
for (x = 0; x < MAX_SCHED; ++x) {
if (ctrl->pri_sched[x].callback && (!closest
|| (closest->tv_sec > ctrl->pri_sched[x].when.tv_sec)
|| ((closest->tv_sec == ctrl->pri_sched[x].when.tv_sec)
&& (closest->tv_usec > ctrl->pri_sched[x].when.tv_usec)))) {
closest = &ctrl->pri_sched[x].when;
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) {
if (!closest) {
/* This is the highest sheduled timer slot in use. */
closest = &ctrl->sched.timer[x].when;
ctrl->sched.max_used = x + 1;
} else if ((closest->tv_sec > ctrl->sched.timer[x].when.tv_sec)
|| ((closest->tv_sec == ctrl->sched.timer[x].when.tv_sec)
&& (closest->tv_usec > ctrl->sched.timer[x].when.tv_usec))) {
closest = &ctrl->sched.timer[x].when;
}
}
}
if (!closest) {
/* No scheduled timer slots are active. */
ctrl->sched.max_used = 0;
}
return closest;
}
@@ -121,23 +191,25 @@ struct timeval *pri_schedule_next(struct pri *ctrl)
*/
static pri_event *__pri_schedule_run(struct pri *ctrl, struct timeval *tv)
{
int x;
unsigned x;
unsigned max_used;
void (*callback)(void *);
void *data;
/* Scheduling runs on master channels only */
while (ctrl->master) {
ctrl = ctrl->master;
}
for (x = 0; x < MAX_SCHED; ++x) {
if (ctrl->pri_sched[x].callback && ((ctrl->pri_sched[x].when.tv_sec < tv->tv_sec)
|| ((ctrl->pri_sched[x].when.tv_sec == tv->tv_sec)
&& (ctrl->pri_sched[x].when.tv_usec <= tv->tv_usec)))) {
ctrl = PRI_MASTER(ctrl);
max_used = ctrl->sched.max_used;
for (x = 0; x < max_used; ++x) {
if (ctrl->sched.timer[x].callback
&& ((ctrl->sched.timer[x].when.tv_sec < tv->tv_sec)
|| ((ctrl->sched.timer[x].when.tv_sec == tv->tv_sec)
&& (ctrl->sched.timer[x].when.tv_usec <= tv->tv_usec)))) {
/* This timer has expired. */
ctrl->schedev = 0;
callback = ctrl->pri_sched[x].callback;
data = ctrl->pri_sched[x].data;
ctrl->pri_sched[x].callback = NULL;
callback = ctrl->sched.timer[x].callback;
data = ctrl->sched.timer[x].data;
ctrl->sched.timer[x].callback = NULL;
callback(data);
if (ctrl->schedev) {
return &ctrl->ev;
@@ -175,12 +247,12 @@ pri_event *pri_schedule_run(struct pri *ctrl)
void pri_schedule_del(struct pri *ctrl, int id)
{
/* Scheduling runs on master channels only */
while (ctrl->master) {
ctrl = ctrl->master;
}
if (0 < id && id <= MAX_SCHED) {
ctrl->pri_sched[id - 1].callback = NULL;
ctrl = PRI_MASTER(ctrl);
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???\n", id);
pri_error(ctrl, "Asked to delete sched id %d??? num_slots=%d\n", id,
ctrl->sched.num_slots);
}
}

View File

@@ -28,7 +28,7 @@
*/
/*
* This program tests libpri call reception using a zaptel interface.
* This program tests libpri call reception using a dahdi interface.
* Its state machines are setup for RECEIVING CALLS ONLY, so if you
* are trying to both place and receive calls you have to a bit more.
*/
@@ -37,6 +37,7 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <unistd.h>
@@ -45,8 +46,8 @@
#include <sys/wait.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <zaptel/zaptel.h>
#include <zap.h>
#include <dahdi/user.h>
#include <dahdi/tonezone.h>
#include "libpri.h"
#define PRI_DEF_NODETYPE PRI_CPE
@@ -55,13 +56,20 @@
#define MAX_CHAN 32
#define DCHANNEL_TIMESLOT 16
#define READ_SIZE 160
static int offset = 0;
static void do_channel(ZAP *z)
static void do_channel(int fd)
{
/* This is the part that runs on a given channel */
zap_playf(z, "raw.ulaw", 0);
char buf[READ_SIZE];
int res;
int i=0;
while ((res = read(fd, buf, READ_SIZE)) > 0 && (i++ < 1000)) {
write(fd, buf, res);
}
}
struct pri_chan {
@@ -141,10 +149,57 @@ static void hangup_channel(int channo)
chans[channo].needhangup = 0;
}
static int dahdi_open(char *fn)
{
int fd;
int isnum;
int chan = 0;
int bs;
int x;
fprintf(stderr, "dahdi open %s\n", fn);
isnum = 1;
for (x = 0; x < strlen(fn); x++) {
if (!isdigit(fn[x])) {
isnum = 0;
break;
}
}
if (isnum) {
chan = atoi(fn);
if (chan < 1) {
printf("Invalid channel number '%s'\n", fn);
exit(1);
}
fn = "/dev/dahdi/channel";
}
fd = open(fn, O_RDWR /* | O_NONBLOCK */);
if (fd < 0) {
printf("Unable to open '%s': %s\n", fn, strerror(errno));
exit(1);
}
if (chan) {
if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
x = errno;
close(fd);
errno = x;
printf("Unable to specify channel %d: %s\n", chan, strerror(errno));
exit(1);
}
}
bs = READ_SIZE;
if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
printf("Unable to set blocksize '%d': %s\n", bs, strerror(errno));
exit(1);
}
return fd;
}
static void launch_channel(int channo)
{
pid_t pid;
ZAP *z;
int z;
char ch[80];
/* Make sure hangup state is reset */
@@ -161,7 +216,7 @@ static void launch_channel(int channo)
chans[channo].pid = pid;
} else {
sprintf(ch, "%d", channo + offset);
z = zap_open(ch, 0);
z = dahdi_open(ch);
if (z) {
do_channel(z);
exit(0);
@@ -299,7 +354,7 @@ static int run_pri(int dfd, int swtype, int node)
fd_set rfds, efds;
int res,x;
pri = pri_new_bri(dfd, 1, node, swtype);
pri = pri_new(dfd, node, swtype);
if (!pri) {
fprintf(stderr, "Unable to create PRI\n");
return -1;
@@ -334,8 +389,8 @@ static int run_pri(int dfd, int swtype, int node)
} else if (res > 0) {
e = pri_check_event(pri);
} else if (errno == ELAST) {
res = ioctl(dfd, ZT_GETEVENT, &x);
printf("Got Zaptel event: %d\n", x);
res = ioctl(dfd, DAHDI_GETEVENT, &x);
printf("Got DAHDI event: %d\n", x);
} else if (errno != EINTR)
fprintf(stderr, "Error (%d) on select: %s\n", ELAST, strerror(errno));
@@ -343,7 +398,7 @@ static int run_pri(int dfd, int swtype, int node)
handle_pri_event(pri, e);
}
res = ioctl(dfd, ZT_GETEVENT, &x);
res = ioctl(dfd, DAHDI_GETEVENT, &x);
if (!res && x) {
fprintf(stderr, "Got event on PRI interface: %d\n", x);
@@ -365,7 +420,7 @@ int main(int argc, char *argv[])
int dfd;
int swtype = PRI_DEF_SWITCHTYPE;
int node = PRI_DEF_NODETYPE;
struct zt_params p;
struct dahdi_params p;
if (argc < 2) {
fprintf(stderr, "Usage: pritest <dchannel> [swtypetype] [nodetype]\n");
exit(1);
@@ -375,11 +430,11 @@ int main(int argc, char *argv[])
fprintf(stderr, "Failed to open dchannel '%s': %s\n", argv[1], strerror(errno));
exit(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", argv[1], strerror(errno));
exit(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", argv[1], p.sigtype);
exit(1);
}

2175
q921.c

File diff suppressed because it is too large Load Diff

1262
q931.c

File diff suppressed because it is too large Load Diff

482
rose.c
View File

@@ -200,6 +200,54 @@ static const struct asn1_oid rose_etsi_ect = {
/* *INDENT-ON* */
};
/*! \brief ETSI Status Request OID prefix. */
static const struct asn1_oid rose_etsi_status_request = {
/* *INDENT-OFF* */
/* {itu-t(0) identified-organization(4) etsi(0) 196 status-request-procedure(9)} */
4, { 4, 0, 196, 9 }
/* *INDENT-ON* */
};
/*! \brief ETSI Call Completion Busy Status OID prefix. */
static const struct asn1_oid rose_etsi_ccbs = {
/* *INDENT-OFF* */
/* {ccitt(0) identified-organization(4) etsi(0) 359 operations-and-errors(1)} */
4, { 4, 0, 359, 1 }
/* *INDENT-ON* */
};
/*! \brief ETSI Call Completion Busy Status public-private interworking OID prefix. */
static const struct asn1_oid rose_etsi_ccbs_t = {
/* *INDENT-OFF* */
/* {ccitt(0) identified-organization(4) etsi(0) 359 private-networks-operations-and-errors(2)} */
4, { 4, 0, 359, 2 }
/* *INDENT-ON* */
};
/*! \brief ETSI Call Completion No Reply OID prefix. */
static const struct asn1_oid rose_etsi_ccnr = {
/* *INDENT-OFF* */
/* {ccitt(0) identified-organization(4) etsi(0) 1065 operations-and-errors(1)} */
4, { 4, 0, 1065, 1 }
/* *INDENT-ON* */
};
/*! \brief ETSI Call Completion No Reply public-private interworking OID prefix. */
static const struct asn1_oid rose_etsi_ccnr_t = {
/* *INDENT-OFF* */
/* {ccitt(0) identified-organization(4) etsi(0) 1065 private-networks-operations-and-errors(2)} */
4, { 4, 0, 1065, 2 }
/* *INDENT-ON* */
};
/*! \brief ETSI Message Waiting Indication OID prefix. */
static const struct asn1_oid rose_etsi_mwi = {
/* *INDENT-OFF* */
/* {ccitt(0) identified-organization(4) etsi(0) 745 operations-and-errors(1)} */
4, { 4, 0, 745, 1 }
/* *INDENT-ON* */
};
/*! \brief ETSI specific invoke/result encode/decode message table */
static const struct rose_convert_msg rose_etsi_msgs[] = {
/* *INDENT-OFF* */
@@ -361,6 +409,166 @@ static const struct rose_convert_msg rose_etsi_msgs[] = {
rose_enc_etsi_EctLoopTest_ARG, rose_enc_etsi_EctLoopTest_RES,
rose_dec_etsi_EctLoopTest_ARG, rose_dec_etsi_EctLoopTest_RES
},
/*
* globalValue's (OIDs) from Status-Request-Procedure
* {itu-t identified-organization etsi(0) 196 status-request-procedure(9)}
*/
{
ROSE_ETSI_StatusRequest, &rose_etsi_status_request, 1,
rose_enc_etsi_StatusRequest_ARG, rose_enc_etsi_StatusRequest_RES,
rose_dec_etsi_StatusRequest_ARG, rose_dec_etsi_StatusRequest_RES
},
/*
* globalValue's (OIDs) from CCBS-Operations-and-Errors
* {ccitt identified-organization etsi(0) 359 operations-and-errors(1)}
*/
{
ROSE_ETSI_CallInfoRetain, &rose_etsi_ccbs, 1,
rose_enc_etsi_CallInfoRetain_ARG, NULL,
rose_dec_etsi_CallInfoRetain_ARG, NULL
},
{
ROSE_ETSI_CCBSRequest, &rose_etsi_ccbs, 2,
rose_enc_etsi_CCBSRequest_ARG, rose_enc_etsi_CCBSRequest_RES,
rose_dec_etsi_CCBSRequest_ARG, rose_dec_etsi_CCBSRequest_RES
},
{
ROSE_ETSI_CCBSDeactivate, &rose_etsi_ccbs, 3,
rose_enc_etsi_CCBSDeactivate_ARG, NULL,
rose_dec_etsi_CCBSDeactivate_ARG, NULL
},
{
ROSE_ETSI_CCBSInterrogate, &rose_etsi_ccbs, 4,
rose_enc_etsi_CCBSInterrogate_ARG, rose_enc_etsi_CCBSInterrogate_RES,
rose_dec_etsi_CCBSInterrogate_ARG, rose_dec_etsi_CCBSInterrogate_RES
},
{
ROSE_ETSI_CCBSErase, &rose_etsi_ccbs, 5,
rose_enc_etsi_CCBSErase_ARG, NULL,
rose_dec_etsi_CCBSErase_ARG, NULL
},
{
ROSE_ETSI_CCBSRemoteUserFree, &rose_etsi_ccbs, 6,
rose_enc_etsi_CCBSRemoteUserFree_ARG, NULL,
rose_dec_etsi_CCBSRemoteUserFree_ARG, NULL
},
{
ROSE_ETSI_CCBSCall, &rose_etsi_ccbs, 7,
rose_enc_etsi_CCBSCall_ARG, NULL,
rose_dec_etsi_CCBSCall_ARG, NULL
},
{
ROSE_ETSI_CCBSStatusRequest, &rose_etsi_ccbs, 8,
rose_enc_etsi_CCBSStatusRequest_ARG, rose_enc_etsi_CCBSStatusRequest_RES,
rose_dec_etsi_CCBSStatusRequest_ARG, rose_dec_etsi_CCBSStatusRequest_RES
},
{
ROSE_ETSI_CCBSBFree, &rose_etsi_ccbs, 9,
rose_enc_etsi_CCBSBFree_ARG, NULL,
rose_dec_etsi_CCBSBFree_ARG, NULL
},
{
ROSE_ETSI_EraseCallLinkageID, &rose_etsi_ccbs, 10,
rose_enc_etsi_EraseCallLinkageID_ARG, NULL,
rose_dec_etsi_EraseCallLinkageID_ARG, NULL
},
{
ROSE_ETSI_CCBSStopAlerting, &rose_etsi_ccbs, 11,
rose_enc_etsi_CCBSStopAlerting_ARG, NULL,
rose_dec_etsi_CCBSStopAlerting_ARG, NULL
},
/*
* globalValue's (OIDs) from CCBS-private-networks-Operations-and-Errors
* {ccitt identified-organization etsi(0) 359 private-networks-operations-and-errors(2)}
*/
{
ROSE_ETSI_CCBS_T_Request, &rose_etsi_ccbs_t, 1,
rose_enc_etsi_CCBS_T_Request_ARG, rose_enc_etsi_CCBS_T_Request_RES,
rose_dec_etsi_CCBS_T_Request_ARG, rose_dec_etsi_CCBS_T_Request_RES
},
{
ROSE_ETSI_CCBS_T_Call, &rose_etsi_ccbs_t, 2,
NULL, NULL,
NULL, NULL
},
{
ROSE_ETSI_CCBS_T_Suspend, &rose_etsi_ccbs_t, 3,
NULL, NULL,
NULL, NULL
},
{
ROSE_ETSI_CCBS_T_Resume, &rose_etsi_ccbs_t, 4,
NULL, NULL,
NULL, NULL
},
{
ROSE_ETSI_CCBS_T_RemoteUserFree, &rose_etsi_ccbs_t, 5,
NULL, NULL,
NULL, NULL
},
{
ROSE_ETSI_CCBS_T_Available, &rose_etsi_ccbs_t, 6,
NULL, NULL,
NULL, NULL
},
/*
* globalValue's (OIDs) from CCNR-Operations-and-Errors
* {ccitt identified-organization etsi(0) 1065 operations-and-errors(1)}
*/
{
ROSE_ETSI_CCNRRequest, &rose_etsi_ccnr, 1,
rose_enc_etsi_CCNRRequest_ARG, rose_enc_etsi_CCNRRequest_RES,
rose_dec_etsi_CCNRRequest_ARG, rose_dec_etsi_CCNRRequest_RES
},
{
ROSE_ETSI_CCNRInterrogate, &rose_etsi_ccnr, 2,
rose_enc_etsi_CCNRInterrogate_ARG, rose_enc_etsi_CCNRInterrogate_RES,
rose_dec_etsi_CCNRInterrogate_ARG, rose_dec_etsi_CCNRInterrogate_RES
},
/*
* globalValue's (OIDs) from CCNR-private-networks-Operations-and-Errors
* {ccitt identified-organization etsi(0) 1065 private-networks-operations-and-errors(2)}
*/
{
ROSE_ETSI_CCNR_T_Request, &rose_etsi_ccnr_t, 1,
rose_enc_etsi_CCNR_T_Request_ARG, rose_enc_etsi_CCNR_T_Request_RES,
rose_dec_etsi_CCNR_T_Request_ARG, rose_dec_etsi_CCNR_T_Request_RES
},
/*
* localValue's from MCID-Operations
* {ccitt identified-organization etsi(0) 130 operations-and-errors(1)}
*/
{
ROSE_ETSI_MCIDRequest, NULL, 3,
NULL, NULL,
NULL, NULL
},
/*
* globalValue's (OIDs) from MWI-Operations-and-Errors
* {ccitt identified-organization etsi(0) 745 operations-and-errors(1)}
*/
{
ROSE_ETSI_MWIActivate, &rose_etsi_mwi, 1,
rose_enc_etsi_MWIActivate_ARG, NULL,
rose_dec_etsi_MWIActivate_ARG, NULL
},
{
ROSE_ETSI_MWIDeactivate, &rose_etsi_mwi, 2,
rose_enc_etsi_MWIDeactivate_ARG, NULL,
rose_dec_etsi_MWIDeactivate_ARG, NULL
},
{
ROSE_ETSI_MWIIndicate, &rose_etsi_mwi, 3,
rose_enc_etsi_MWIIndicate_ARG, NULL,
rose_dec_etsi_MWIIndicate_ARG, NULL
},
/* *INDENT-ON* */
};
@@ -463,6 +671,89 @@ static const struct rose_convert_error rose_etsi_errors[] = {
ROSE_ERROR_ECT_LinkIdNotAssignedByNetwork, &rose_etsi_ect, 21,
NULL, NULL
},
/*
* globalValue Errors (OIDs) from CCBS-Operations-and-Errors
* {ccitt identified-organization etsi(0) 359 operations-and-errors(1)}
*/
{
ROSE_ERROR_CCBS_InvalidCallLinkageID, &rose_etsi_ccbs, 20,
NULL, NULL
},
{
ROSE_ERROR_CCBS_InvalidCCBSReference, &rose_etsi_ccbs, 21,
NULL, NULL
},
{
ROSE_ERROR_CCBS_LongTermDenial, &rose_etsi_ccbs, 22,
NULL, NULL
},
{
ROSE_ERROR_CCBS_ShortTermDenial, &rose_etsi_ccbs, 23,
NULL, NULL
},
{
ROSE_ERROR_CCBS_IsAlreadyActivated, &rose_etsi_ccbs, 24,
NULL, NULL
},
{
ROSE_ERROR_CCBS_AlreadyAccepted, &rose_etsi_ccbs, 25,
NULL, NULL
},
{
ROSE_ERROR_CCBS_OutgoingCCBSQueueFull, &rose_etsi_ccbs, 26,
NULL, NULL
},
{
ROSE_ERROR_CCBS_CallFailureReasonNotBusy, &rose_etsi_ccbs, 27,
NULL, NULL
},
{
ROSE_ERROR_CCBS_NotReadyForCall, &rose_etsi_ccbs, 28,
NULL, NULL
},
/*
* globalValue Errors (OIDs) from CCBS-private-networks-Operations-and-Errors
* {ccitt identified-organization etsi(0) 359 private-networks-operations-and-errors(2)}
*/
{
ROSE_ERROR_CCBS_T_LongTermDenial, &rose_etsi_ccbs_t, 20,
NULL, NULL
},
{
ROSE_ERROR_CCBS_T_ShortTermDenial, &rose_etsi_ccbs_t, 21,
NULL, NULL
},
/*
* globalValue's (OIDs) from MWI-Operations-and-Errors
* {ccitt identified-organization etsi(0) 745 operations-and-errors(1)}
*/
{
ROSE_ERROR_MWI_InvalidReceivingUserNr, &rose_etsi_mwi, 10,
NULL, NULL
},
{
ROSE_ERROR_MWI_ReceivingUserNotSubscribed, &rose_etsi_mwi, 11,
NULL, NULL
},
{
ROSE_ERROR_MWI_ControllingUserNotRegistered,&rose_etsi_mwi, 12,
NULL, NULL
},
{
ROSE_ERROR_MWI_IndicationNotDelivered, &rose_etsi_mwi, 13,
NULL, NULL
},
{
ROSE_ERROR_MWI_MaxNumOfControllingUsersReached,&rose_etsi_mwi, 14,
NULL, NULL
},
{
ROSE_ERROR_MWI_MaxNumOfActiveInstancesReached,&rose_etsi_mwi, 15,
NULL, NULL
},
/* *INDENT-ON* */
};
@@ -470,6 +761,21 @@ static const struct rose_convert_error rose_etsi_errors[] = {
/* ------------------------------------------------------------------- */
/*
* Note the first value in oid.values[] is really the first two
* OID subidentifiers. They are compressed using this formula:
* First_Value = (First_Subidentifier * 40) + Second_Subidentifier
*/
/*! \brief ECMA private-isdn-signalling-domain prefix. */
static const struct asn1_oid rose_qsig_isdn_domain = {
/* *INDENT-OFF* */
/* {iso(1) identified-organization(3) icd-ecma(12) private-isdn-signalling-domain(9)} */
3, { 43, 12, 9 }
/* *INDENT-ON* */
};
/*! \brief Q.SIG specific invoke/result encode/decode message table */
static const struct rose_convert_msg rose_qsig_msgs[] = {
/* *INDENT-OFF* */
@@ -479,7 +785,7 @@ static const struct rose_convert_msg rose_qsig_msgs[] = {
* decode_invoke_args, decode_result_args
*/
/*
* localValue's from Q.SIG Name-Operations
* localValue's from Q.SIG Name-Operations 4th edition
* { iso(1) standard(0) pss1-name(13868) name-operations(0) }
*/
{
@@ -503,6 +809,34 @@ static const struct rose_convert_msg rose_qsig_msgs[] = {
rose_dec_qsig_BusyName_ARG, NULL
},
/*
* globalValue's (OIDs) from Q.SIG Name-Operations 2nd edition
* { iso(1) identified-organization(3) icd-ecma(12) standard(0) qsig-name(164) name-operations(0) }
*
* This older version of the Q.SIG switch is not supported.
* However, we will accept receiving these messages anyway.
*/
{
ROSE_QSIG_CallingName, &rose_qsig_isdn_domain, 0,
rose_enc_qsig_CallingName_ARG, NULL,
rose_dec_qsig_CallingName_ARG, NULL
},
{
ROSE_QSIG_CalledName, &rose_qsig_isdn_domain, 1,
rose_enc_qsig_CalledName_ARG, NULL,
rose_dec_qsig_CalledName_ARG, NULL
},
{
ROSE_QSIG_ConnectedName, &rose_qsig_isdn_domain, 2,
rose_enc_qsig_ConnectedName_ARG, NULL,
rose_dec_qsig_ConnectedName_ARG, NULL
},
{
ROSE_QSIG_BusyName, &rose_qsig_isdn_domain, 3,
rose_enc_qsig_BusyName_ARG, NULL,
rose_dec_qsig_BusyName_ARG, NULL
},
/*
* localValue's from Q.SIG SS-AOC-Operations
* { iso(1) standard(0) pss1-advice-of-charge(15050) advice-of-charge-operations(0) }
@@ -649,6 +983,51 @@ static const struct rose_convert_msg rose_qsig_msgs[] = {
rose_dec_qsig_DummyArg_ARG, NULL
},
/*
* localValue's from Q.SIG SS-CC-Operations
* { iso(1) standard(0) pss1-call-completion(13870) operations(0) }
*/
{
ROSE_QSIG_CcbsRequest, NULL, 40,
rose_enc_qsig_CcbsRequest_ARG, rose_enc_qsig_CcbsRequest_RES,
rose_dec_qsig_CcbsRequest_ARG, rose_dec_qsig_CcbsRequest_RES
},
{
ROSE_QSIG_CcnrRequest, NULL, 27,
rose_enc_qsig_CcnrRequest_ARG, rose_enc_qsig_CcnrRequest_RES,
rose_dec_qsig_CcnrRequest_ARG, rose_dec_qsig_CcnrRequest_RES
},
{
ROSE_QSIG_CcCancel, NULL, 28,
rose_enq_qsig_CcCancel_ARG, NULL,
rose_dec_qsig_CcCancel_ARG, NULL
},
{
ROSE_QSIG_CcExecPossible, NULL, 29,
rose_enq_qsig_CcExecPossible_ARG, NULL,
rose_dec_qsig_CcExecPossible_ARG, NULL
},
{
ROSE_QSIG_CcPathReserve, NULL, 30,
rose_enc_qsig_CcPathReserve_ARG, rose_enc_qsig_CcPathReserve_RES,
rose_dec_qsig_CcPathReserve_ARG, rose_dec_qsig_CcPathReserve_RES
},
{
ROSE_QSIG_CcRingout, NULL, 31,
rose_enc_qsig_CcRingout_ARG, NULL,
rose_dec_qsig_CcRingout_ARG, NULL
},
{
ROSE_QSIG_CcSuspend, NULL, 32,
rose_enc_qsig_CcSuspend_ARG, NULL,
rose_dec_qsig_CcSuspend_ARG, NULL
},
{
ROSE_QSIG_CcResume, NULL, 33,
rose_enc_qsig_CcResume_ARG, NULL,
rose_dec_qsig_CcResume_ARG, NULL
},
/*
* localValue's from Q.SIG SS-MWI-Operations
* { iso(1) standard(0) pss1-message-waiting-indication(15506) message-waiting-operations(0) }
@@ -800,6 +1179,31 @@ static const struct rose_convert_error rose_qsig_errors[] = {
NULL, NULL
},
/*
* localValue's from Q.SIG SS-CC-Operations
* { iso(1) standard(0) pss1-call-completion(13870) operations(0) }
*/
{
ROSE_ERROR_QSIG_ShortTermRejection, NULL, 1010,
NULL, NULL
},
{
ROSE_ERROR_QSIG_LongTermRejection, NULL, 1011,
NULL, NULL
},
{
ROSE_ERROR_QSIG_RemoteUserBusyAgain, NULL, 1012,
NULL, NULL
},
{
ROSE_ERROR_QSIG_FailureToMatch, NULL, 1013,
NULL, NULL
},
{
ROSE_ERROR_QSIG_FailedDueToInterworking, NULL, 1014,
NULL, NULL
},
/*
* localValue's from Q.SIG SS-MWI-Operations
* { iso(1) standard(0) pss1-message-waiting-indication(15506) message-waiting-operations(0) }
@@ -1069,6 +1473,40 @@ const char *rose_operation2str(enum rose_operation operation)
{ ROSE_ETSI_AOCECurrency, "ROSE_ETSI_AOCECurrency" },
{ ROSE_ETSI_AOCEChargingUnit, "ROSE_ETSI_AOCEChargingUnit" },
{ ROSE_ETSI_StatusRequest, "ROSE_ETSI_StatusRequest" },
{ ROSE_ETSI_CallInfoRetain, "ROSE_ETSI_CallInfoRetain" },
{ ROSE_ETSI_EraseCallLinkageID, "ROSE_ETSI_EraseCallLinkageID" },
{ ROSE_ETSI_CCBSDeactivate, "ROSE_ETSI_CCBSDeactivate" },
{ ROSE_ETSI_CCBSErase, "ROSE_ETSI_CCBSErase" },
{ ROSE_ETSI_CCBSRemoteUserFree, "ROSE_ETSI_CCBSRemoteUserFree" },
{ ROSE_ETSI_CCBSCall, "ROSE_ETSI_CCBSCall" },
{ ROSE_ETSI_CCBSStatusRequest, "ROSE_ETSI_CCBSStatusRequest" },
{ ROSE_ETSI_CCBSBFree, "ROSE_ETSI_CCBSBFree" },
{ ROSE_ETSI_CCBSStopAlerting, "ROSE_ETSI_CCBSStopAlerting" },
{ ROSE_ETSI_CCBSRequest, "ROSE_ETSI_CCBSRequest" },
{ ROSE_ETSI_CCBSInterrogate, "ROSE_ETSI_CCBSInterrogate" },
{ ROSE_ETSI_CCNRRequest, "ROSE_ETSI_CCNRRequest" },
{ ROSE_ETSI_CCNRInterrogate, "ROSE_ETSI_CCNRInterrogate" },
{ ROSE_ETSI_CCBS_T_Call, "ROSE_ETSI_CCBS_T_Call" },
{ ROSE_ETSI_CCBS_T_Suspend, "ROSE_ETSI_CCBS_T_Suspend" },
{ ROSE_ETSI_CCBS_T_Resume, "ROSE_ETSI_CCBS_T_Resume" },
{ ROSE_ETSI_CCBS_T_RemoteUserFree, "ROSE_ETSI_CCBS_T_RemoteUserFree" },
{ ROSE_ETSI_CCBS_T_Available, "ROSE_ETSI_CCBS_T_Available" },
{ ROSE_ETSI_CCBS_T_Request, "ROSE_ETSI_CCBS_T_Request" },
{ ROSE_ETSI_CCNR_T_Request, "ROSE_ETSI_CCNR_T_Request" },
{ ROSE_ETSI_MCIDRequest, "ROSE_ETSI_MCIDRequest" },
{ ROSE_ETSI_MWIActivate, "ROSE_ETSI_MWIActivate" },
{ ROSE_ETSI_MWIDeactivate, "ROSE_ETSI_MWIDeactivate" },
{ ROSE_ETSI_MWIIndicate, "ROSE_ETSI_MWIIndicate" },
{ ROSE_QSIG_CallingName, "ROSE_QSIG_CallingName" },
{ ROSE_QSIG_CalledName, "ROSE_QSIG_CalledName" },
{ ROSE_QSIG_ConnectedName, "ROSE_QSIG_ConnectedName" },
@@ -1103,6 +1541,15 @@ const char *rose_operation2str(enum rose_operation operation)
{ ROSE_QSIG_DivertingLegInformation3, "ROSE_QSIG_DivertingLegInformation3" },
{ ROSE_QSIG_CfnrDivertedLegFailed, "ROSE_QSIG_CfnrDivertedLegFailed" },
{ ROSE_QSIG_CcbsRequest, "ROSE_QSIG_CcbsRequest" },
{ ROSE_QSIG_CcnrRequest, "ROSE_QSIG_CcnrRequest" },
{ ROSE_QSIG_CcCancel, "ROSE_QSIG_CcCancel" },
{ ROSE_QSIG_CcExecPossible, "ROSE_QSIG_CcExecPossible" },
{ ROSE_QSIG_CcPathReserve, "ROSE_QSIG_CcPathReserve" },
{ ROSE_QSIG_CcRingout, "ROSE_QSIG_CcRingout" },
{ ROSE_QSIG_CcSuspend, "ROSE_QSIG_CcSuspend" },
{ ROSE_QSIG_CcResume, "ROSE_QSIG_CcResume" },
{ ROSE_QSIG_MWIActivate, "ROSE_QSIG_MWIActivate" },
{ ROSE_QSIG_MWIDeactivate, "ROSE_QSIG_MWIDeactivate" },
{ ROSE_QSIG_MWIInterrogate, "ROSE_QSIG_MWIInterrogate" },
@@ -1161,6 +1608,26 @@ const char *rose_error2str(enum rose_error_code code)
{ ROSE_ERROR_ECT_LinkIdNotAssignedByNetwork, "ECT: Link ID Not Assigned By Network" },
{ ROSE_ERROR_CCBS_InvalidCallLinkageID, "CCBS: Invalid Call Linkage ID" },
{ ROSE_ERROR_CCBS_InvalidCCBSReference, "CCBS: Invalid CCBS Reference" },
{ ROSE_ERROR_CCBS_LongTermDenial, "CCBS: Long Term Denial" },
{ ROSE_ERROR_CCBS_ShortTermDenial, "CCBS: Short Term Denial" },
{ ROSE_ERROR_CCBS_IsAlreadyActivated, "CCBS: Is Already Activated" },
{ ROSE_ERROR_CCBS_AlreadyAccepted, "CCBS: Already Accepted" },
{ ROSE_ERROR_CCBS_OutgoingCCBSQueueFull, "CCBS: Outgoing CCBS Queue Full" },
{ ROSE_ERROR_CCBS_CallFailureReasonNotBusy, "CCBS: Call Failure Reason Not Busy" },
{ ROSE_ERROR_CCBS_NotReadyForCall, "CCBS: Not Ready For Call" },
{ ROSE_ERROR_CCBS_T_LongTermDenial, "CCBS-T: Long Term Denial" },
{ ROSE_ERROR_CCBS_T_ShortTermDenial, "CCBS-T: Short Term Denial" },
{ ROSE_ERROR_MWI_InvalidReceivingUserNr, "MWI: Invalid Receiving User Number" },
{ ROSE_ERROR_MWI_ReceivingUserNotSubscribed, "MWI: Receiving User Not Subscribed" },
{ ROSE_ERROR_MWI_ControllingUserNotRegistered,"MWI: Controlling User Not Registered" },
{ ROSE_ERROR_MWI_IndicationNotDelivered, "MWI: Indication Not Delivered" },
{ ROSE_ERROR_MWI_MaxNumOfControllingUsersReached,"MWI: Max Num Of Controlling Users Reached" },
{ ROSE_ERROR_MWI_MaxNumOfActiveInstancesReached,"MWI: Max Num Of Active Instances Reached" },
/* Q.SIG specific errors */
{ ROSE_ERROR_QSIG_Unspecified, "Unspecified" },
@@ -1173,6 +1640,12 @@ const char *rose_error2str(enum rose_error_code code)
{ ROSE_ERROR_QSIG_Div_TemporarilyUnavailable, "Diversion: Temporarily Unavailable" },
{ ROSE_ERROR_QSIG_Div_NotAuthorized, "Diversion: Not Authorized" },
{ ROSE_ERROR_QSIG_ShortTermRejection, "CC: Short Term Rejection" },
{ ROSE_ERROR_QSIG_LongTermRejection, "CC: Long Term Rejection" },
{ ROSE_ERROR_QSIG_RemoteUserBusyAgain, "CC: Remote User Busy Again" },
{ ROSE_ERROR_QSIG_FailureToMatch, "CC: Failure To Match" },
{ ROSE_ERROR_QSIG_FailedDueToInterworking, "CC: Failed Due To Interworking" },
{ ROSE_ERROR_QSIG_InvalidMsgCentreId, "MWI: Invalid Message Center ID" },
/* DMS-100 specific errors */
@@ -2241,13 +2714,6 @@ const unsigned char *rose_decode(struct pri *ctrl, const unsigned char *pos,
return NULL;
}
if (pos < end) {
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %u byte(s) of trailing data not consumed.\n",
(unsigned) (end - pos));
}
}
return pos;
}

856
rose.h
View File

@@ -103,6 +103,45 @@ enum rose_operation {
ROSE_ETSI_EctInform, /*!< Invoke only */
ROSE_ETSI_EctLoopTest, /*!< Invoke/Result */
/* ETSI Status-Request-Procedure */
ROSE_ETSI_StatusRequest, /*!< Invoke/Result */
/* ETSI CCBS-Operations-and-Errors */
ROSE_ETSI_CallInfoRetain, /*!< Invoke only */
ROSE_ETSI_CCBSRequest, /*!< Invoke/Result */
ROSE_ETSI_CCBSDeactivate, /*!< Invoke/Result */
ROSE_ETSI_CCBSInterrogate, /*!< Invoke/Result */
ROSE_ETSI_CCBSErase, /*!< Invoke only */
ROSE_ETSI_CCBSRemoteUserFree, /*!< Invoke only */
ROSE_ETSI_CCBSCall, /*!< Invoke only */
ROSE_ETSI_CCBSStatusRequest, /*!< Invoke/Result */
ROSE_ETSI_CCBSBFree, /*!< Invoke only */
ROSE_ETSI_EraseCallLinkageID, /*!< Invoke only */
ROSE_ETSI_CCBSStopAlerting, /*!< Invoke only */
/* ETSI CCBS-private-networks-Operations-and-Errors */
ROSE_ETSI_CCBS_T_Request, /*!< Invoke/Result */
ROSE_ETSI_CCBS_T_Call, /*!< Invoke only */
ROSE_ETSI_CCBS_T_Suspend, /*!< Invoke only */
ROSE_ETSI_CCBS_T_Resume, /*!< Invoke only */
ROSE_ETSI_CCBS_T_RemoteUserFree, /*!< Invoke only */
ROSE_ETSI_CCBS_T_Available, /*!< Invoke only */
/* ETSI CCNR-Operations-and-Errors */
ROSE_ETSI_CCNRRequest, /*!< Invoke/Result */
ROSE_ETSI_CCNRInterrogate, /*!< Invoke/Result */
/* ETSI CCNR-private-networks-Operations-and-Errors */
ROSE_ETSI_CCNR_T_Request, /*!< Invoke/Result */
/* ETSI MCID-Operations */
ROSE_ETSI_MCIDRequest, /*!< Invoke/Result */
/* ETSI MWI-Operations-and-Errors */
ROSE_ETSI_MWIActivate, /*!< Invoke/Result */
ROSE_ETSI_MWIDeactivate, /*!< Invoke/Result */
ROSE_ETSI_MWIIndicate, /*!< Invoke only */
/* Q.SIG Name-Operations */
ROSE_QSIG_CallingName, /*!< Invoke only */
ROSE_QSIG_CalledName, /*!< Invoke only */
@@ -141,6 +180,16 @@ enum rose_operation {
ROSE_QSIG_DivertingLegInformation3, /*!< Invoke only */
ROSE_QSIG_CfnrDivertedLegFailed, /*!< Invoke only */
/* Q.SIG SS-CC-Operations */
ROSE_QSIG_CcbsRequest, /*!< Invoke/Result */
ROSE_QSIG_CcnrRequest, /*!< Invoke/Result */
ROSE_QSIG_CcCancel, /*!< Invoke only */
ROSE_QSIG_CcExecPossible, /*!< Invoke only */
ROSE_QSIG_CcPathReserve, /*!< Invoke/Result */
ROSE_QSIG_CcRingout, /*!< Invoke only */
ROSE_QSIG_CcSuspend, /*!< Invoke only */
ROSE_QSIG_CcResume, /*!< Invoke only */
/* Q.SIG SS-MWI-Operations */
ROSE_QSIG_MWIActivate, /*!< Invoke/Result */
ROSE_QSIG_MWIDeactivate, /*!< Invoke/Result */
@@ -198,6 +247,29 @@ enum rose_error_code {
/* ETSI Explicit-Call-Transfer-Operations-and-Errors */
ROSE_ERROR_ECT_LinkIdNotAssignedByNetwork,
/* ETSI CCBS-Operations-and-Errors */
ROSE_ERROR_CCBS_InvalidCallLinkageID,
ROSE_ERROR_CCBS_InvalidCCBSReference,
ROSE_ERROR_CCBS_LongTermDenial,
ROSE_ERROR_CCBS_ShortTermDenial,
ROSE_ERROR_CCBS_IsAlreadyActivated,
ROSE_ERROR_CCBS_AlreadyAccepted,
ROSE_ERROR_CCBS_OutgoingCCBSQueueFull,
ROSE_ERROR_CCBS_CallFailureReasonNotBusy,
ROSE_ERROR_CCBS_NotReadyForCall,
/* ETSI CCBS-private-networks-Operations-and-Errors */
ROSE_ERROR_CCBS_T_LongTermDenial,
ROSE_ERROR_CCBS_T_ShortTermDenial,
/* ETSI MWI-Operations-and-Errors */
ROSE_ERROR_MWI_InvalidReceivingUserNr,
ROSE_ERROR_MWI_ReceivingUserNotSubscribed,
ROSE_ERROR_MWI_ControllingUserNotRegistered,
ROSE_ERROR_MWI_IndicationNotDelivered,
ROSE_ERROR_MWI_MaxNumOfControllingUsersReached,
ROSE_ERROR_MWI_MaxNumOfActiveInstancesReached,
/* Q.SIG from various specifications */
ROSE_ERROR_QSIG_Unspecified,
@@ -213,6 +285,13 @@ enum rose_error_code {
ROSE_ERROR_QSIG_Div_TemporarilyUnavailable,
ROSE_ERROR_QSIG_Div_NotAuthorized,
/* Q.SIG SS-CC-Operations */
ROSE_ERROR_QSIG_ShortTermRejection,
ROSE_ERROR_QSIG_LongTermRejection,
ROSE_ERROR_QSIG_RemoteUserBusyAgain,
ROSE_ERROR_QSIG_FailureToMatch,
ROSE_ERROR_QSIG_FailedDueToInterworking,
/* Q.SIG SS-MWI-Operations */
ROSE_ERROR_QSIG_InvalidMsgCentreId,
@@ -324,6 +403,31 @@ enum {
/* ------------------------------------------------------------------- */
/*
* Comment obtained from ECMA-242 ASN.1 source.
* a VisibleString containing:
* - the (local) date in 8 digits (YYYYMMDD),
* - followed by (local) time of day in 4 or 6 digits (HHMM[SS]),
* - optionally followed by the letter "Z" or
* by a local time differential in 5 digits ("+"HHMM or "-"HHMM);
* this date and time representation follows ISO 8601
* Examples:
* 1) 19970621194530, meaning 21 June 1997, 19:45:30;
* 2) 19970621194530Z, meaning the same as 1);
* 3) 19970621194530-0500, meaning the same as 1),
* 5 hours retarded in relation to UTC time
*
* GeneralizedTime ::= [UNIVERSAL 24] IMPLICIT VisibleString
*/
struct roseGeneralizedTime {
/*! GeneralizedTime (SIZE (12..19)) */
unsigned char str[19 + 1];
};
/* ------------------------------------------------------------------- */
/*
* PartyNumber ::= CHOICE {
* -- the numbering plan is the default numbering plan of
@@ -1671,6 +1775,551 @@ struct roseEtsiEctLoopTest_RES {
/* ------------------------------------------------------------------- */
/*
* ARGUMENT SEQUENCE {
* compatibilityMode CompatibilityMode,
*
* -- The BC, HLC (optional) and LLC (optional) information
* -- elements shall be embedded in q931InfoElement
* q931InformationElement Q931InformationElement
* }
*/
struct roseEtsiStatusRequest_ARG {
/*! \brief The BC, HLC (optional) and LLC (optional) information */
struct roseQ931ie q931ie;
/*! \brief q931ie.contents "allocated" after the stucture. */
unsigned char q931ie_contents[ROSE_Q931_MAX_BC + ROSE_Q931_MAX_HLC +
ROSE_Q931_MAX_LLC + 1];
/*! \details allBasicServices(0), oneOrMoreBasicServices(1) */
u_int8_t compatibility_mode;
};
/*
* RESULT StatusResult
*/
struct roseEtsiStatusRequest_RES {
/*! \details compatibleAndFree(0), compatibleAndBusy(1), incompatible(2) */
u_int8_t status;
};
/* ------------------------------------------------------------------- */
/*
* CallLinkageID ::= INTEGER (0..127)
* CCBSReference ::= INTEGER (0..127)
*/
/*
* ARGUMENT callLinkageID CallLinkageID
*/
struct roseEtsiCallInfoRetain_ARG {
/*! \brief Call Linkage Record ID */
u_int8_t call_linkage_id;
};
/*
* ARGUMENT callLinkageID CallLinkageID
*/
struct roseEtsiEraseCallLinkageID_ARG {
/*! \brief Call Linkage Record ID */
u_int8_t call_linkage_id;
};
/*
* ARGUMENT callLinkageID CallLinkageID
*/
struct roseEtsiCCBSRequest_ARG {
/*! \brief Call Linkage Record ID */
u_int8_t call_linkage_id;
};
/*
* RESULT SEQUENCE {
* recallMode RecallMode,
* cCBSReference CCBSReference
* }
*/
struct roseEtsiCCBSRequest_RES {
/*! \details globalRecall(0), specificRecall(1) */
u_int8_t recall_mode;
/*! \brief CCBS Record ID */
u_int8_t ccbs_reference;
};
/*
* ARGUMENT cCBSReference CCBSReference
*/
struct roseEtsiCCBSDeactivate_ARG {
/*! \brief CCBS Record ID */
u_int8_t ccbs_reference;
};
/*
* ARGUMENT SEQUENCE {
* cCBSReference CCBSReference OPTIONAL,
* partyNumberOfA PartyNumber OPTIONAL
* }
*/
struct roseEtsiCCBSInterrogate_ARG {
/*! \brief Party A number (Optional) */
struct rosePartyNumber a_party_number;
/*! \brief TRUE if CCBSReference present */
u_int8_t ccbs_reference_present;
/*! \brief CCBS Record ID (optional) */
u_int8_t ccbs_reference;
};
/*
* -- The Bearer capability, High layer compatibility (optional)
* -- and Low layer compatibility (optional) information elements
* -- shall be embedded in q931InfoElement.
* CallInformation ::= SEQUENCE {
* addressOfB Address,
* q931InfoElement Q931InformationElement,
* cCBSReference CCBSReference,
* subAddressOfA PartySubaddress OPTIONAL
* }
*/
struct roseEtsiCallInformation {
/*! \brief The BC, HLC (optional) and LLC (optional) information */
struct roseQ931ie q931ie;
/*! \brief q931ie.contents "allocated" after the stucture. */
unsigned char q931ie_contents[ROSE_Q931_MAX_BC + ROSE_Q931_MAX_HLC +
ROSE_Q931_MAX_LLC + 1];
/*! \brief Address of B */
struct roseAddress address_of_b;
/*! \brief Subaddress of A (Optional) */
struct rosePartySubaddress subaddress_of_a;
/*! \brief CCBS Record ID */
u_int8_t ccbs_reference;
};
/*
* CallDetails ::= SEQUENCE SIZE(1..5) OF CallInformation
*/
struct roseEtsiCallDetailsList {
struct roseEtsiCallInformation list[5];
/*! \brief Number of CallDetails records present */
u_int8_t num_records;
};
/*
* RESULT SEQUENCE {
* recallMode RecallMode,
* callDetails CallDetails OPTIONAL
* }
*/
struct roseEtsiCCBSInterrogate_RES {
struct roseEtsiCallDetailsList call_details;
/*! \details globalRecall(0), specificRecall(1) */
u_int8_t recall_mode;
};
/*
* ARGUMENT SEQUENCE {
* recallMode RecallMode,
* cCBSReference CCBSReference,
* addressOfB Address,
* q931InfoElement Q931InformationElement,
* eraseReason CCBSEraseReason
* }
*/
struct roseEtsiCCBSErase_ARG {
/*! \brief The BC, HLC (optional) and LLC (optional) information */
struct roseQ931ie q931ie;
/*! \brief q931ie.contents "allocated" after the stucture. */
unsigned char q931ie_contents[ROSE_Q931_MAX_BC + ROSE_Q931_MAX_HLC +
ROSE_Q931_MAX_LLC + 1];
/*! \brief Address of B */
struct roseAddress address_of_b;
/*! \details globalRecall(0), specificRecall(1) */
u_int8_t recall_mode;
/*! \brief CCBS Record ID */
u_int8_t ccbs_reference;
/*!
* \brief CCBS Erase reason
* \details
* normal-unspecified(0),
* t-CCBS2-timeout(1),
* t-CCBS3-timeout(2),
* basic-call-failed(3)
*/
u_int8_t reason;
};
/*
* ARGUMENT SEQUENCE {
* recallMode RecallMode,
* cCBSReference CCBSReference,
* addressOfB Address,
* q931InfoElement Q931InformationElement
* }
*/
struct roseEtsiCCBSRemoteUserFree_ARG {
/*! \brief The BC, HLC (optional) and LLC (optional) information */
struct roseQ931ie q931ie;
/*! \brief q931ie.contents "allocated" after the stucture. */
unsigned char q931ie_contents[ROSE_Q931_MAX_BC + ROSE_Q931_MAX_HLC +
ROSE_Q931_MAX_LLC + 1];
/*! \brief Address of B */
struct roseAddress address_of_b;
/*! \details globalRecall(0), specificRecall(1) */
u_int8_t recall_mode;
/*! \brief CCBS Record ID */
u_int8_t ccbs_reference;
};
/*
* ARGUMENT cCBSReference CCBSReference
*/
struct roseEtsiCCBSCall_ARG {
/*! \brief CCBS Record ID */
u_int8_t ccbs_reference;
};
/*
* ARGUMENT SEQUENCE {
* recallMode RecallMode,
* cCBSReference CCBSReference,
* q931InfoElement Q931InformationElement
* }
*/
struct roseEtsiCCBSStatusRequest_ARG {
/*! \brief The BC, HLC (optional) and LLC (optional) information */
struct roseQ931ie q931ie;
/*! \brief q931ie.contents "allocated" after the stucture. */
unsigned char q931ie_contents[ROSE_Q931_MAX_BC + ROSE_Q931_MAX_HLC +
ROSE_Q931_MAX_LLC + 1];
/*! \details globalRecall(0), specificRecall(1) */
u_int8_t recall_mode;
/*! \brief CCBS Record ID */
u_int8_t ccbs_reference;
};
/*
* RESULT BOOLEAN -- free=TRUE, busy=FALSE
*/
struct roseEtsiCCBSStatusRequest_RES {
/*! \brief TRUE if User A is free */
u_int8_t free;
};
/*
* ARGUMENT SEQUENCE {
* recallMode RecallMode,
* cCBSReference CCBSReference,
* addressOfB Address,
* q931InfoElement Q931InformationElement
* }
*/
struct roseEtsiCCBSBFree_ARG {
/*! \brief The BC, HLC (optional) and LLC (optional) information */
struct roseQ931ie q931ie;
/*! \brief q931ie.contents "allocated" after the stucture. */
unsigned char q931ie_contents[ROSE_Q931_MAX_BC + ROSE_Q931_MAX_HLC +
ROSE_Q931_MAX_LLC + 1];
/*! \brief Address of B */
struct roseAddress address_of_b;
/*! \details globalRecall(0), specificRecall(1) */
u_int8_t recall_mode;
/*! \brief CCBS Record ID */
u_int8_t ccbs_reference;
};
/*
* ARGUMENT cCBSReference CCBSReference
*/
struct roseEtsiCCBSStopAlerting_ARG {
/*! \brief CCBS Record ID */
u_int8_t ccbs_reference;
};
/* ------------------------------------------------------------------- */
/*
* ARGUMENT SEQUENCE {
* destinationAddress Address,
*
* -- contains HLC, LLC and BC information
* q931InfoElement Q931InformationElement,
*
* retentionSupported [1] IMPLICIT BOOLEAN DEFAULT FALSE,
*
* -- The use of this parameter is specified in
* -- EN 300 195-1 for interaction of CCBS with CLIP
* presentationAllowedIndicator [2] IMPLICIT BOOLEAN OPTIONAL,
*
* -- The use of this parameter is specified in
* -- EN 300 195-1 for interaction of CCBS with CLIP
* originatingAddress Address OPTIONAL
* }
*/
struct roseEtsiCCBS_T_Request_ARG {
/*! \brief The BC, HLC (optional) and LLC (optional) information */
struct roseQ931ie q931ie;
/*! \brief q931ie.contents "allocated" after the stucture. */
unsigned char q931ie_contents[ROSE_Q931_MAX_BC + ROSE_Q931_MAX_HLC +
ROSE_Q931_MAX_LLC + 1];
/*! \brief Address of B */
struct roseAddress destination;
/*! \brief Caller-ID Address (Present if Originating.Party.LengthOfNumber is nonzero) */
struct roseAddress originating;
/*! \brief TRUE if the PresentationAllowedIndicator is present */
u_int8_t presentation_allowed_indicator_present;
/*! \brief TRUE if presentation is allowed for the originating address (optional) */
u_int8_t presentation_allowed_indicator;
/*! \brief TRUE if User A's CCBS request is continued if user B is busy again. */
u_int8_t retention_supported;
};
/*
* RESULT retentionSupported BOOLEAN -- Default False
*/
struct roseEtsiCCBS_T_Request_RES {
/*! \brief TRUE if User A's CCBS request is continued if user B is busy again. */
u_int8_t retention_supported;
};
/* ------------------------------------------------------------------- */
/*
* MessageID ::= SEQUENCE {
* messageRef MessageRef,
* status MessageStatus
* }
*/
struct roseEtsiMessageID {
/*! \brief Message reference number. (INTEGER (0..65535)) */
u_int16_t reference_number;
/*!
* \brief Message status
* \details
* added_message(0),
* removed_message(1)
*/
u_int8_t status;
};
/*
* ARGUMENT SEQUENCE {
* receivingUserNr PartyNumber,
* basicService BasicService,
* controllingUserNr [1] EXPLICIT PartyNumber OPTIONAL,
* numberOfMessages [2] EXPLICIT MessageCounter OPTIONAL,
* controllingUserProvidedNr [3] EXPLICIT PartyNumber OPTIONAL,
* time [4] EXPLICIT GeneralizedTime OPTIONAL,
* messageId [5] EXPLICIT MessageID OPTIONAL,
* mode [6] EXPLICIT InvocationMode OPTIONAL
* }
*/
struct roseEtsiMWIActivate_ARG {
/*! \brief Number of messages in mailbox. (INTEGER (0..65535)) (Optional) */
u_int16_t number_of_messages;
/*! \brief Message ID (Status of this message) (Optional)*/
struct roseEtsiMessageID message_id;
/*! \brief Receiving user number (Who the message is for.) */
struct rosePartyNumber receiving_user_number;
/*! \brief Controlling user number (Mailbox number) (Optional) */
struct rosePartyNumber controlling_user_number;
/*! \brief Controlling user provided number (Caller-ID of party leaving message) (Optional) */
struct rosePartyNumber controlling_user_provided_number;
/*! \brief When message left. (optional) */
struct roseGeneralizedTime time;
/*!
* \brief Type of call leaving message.
* \details
* allServices(0),
* speech(1),
* unrestrictedDigitalInformation(2),
* audio3k1Hz(3),
* unrestrictedDigitalInformationWithTonesAndAnnouncements(4),
* multirate(5),
* telephony3k1Hz(32),
* teletex(33),
* telefaxGroup4Class1(34),
* videotexSyntaxBased(35),
* videotelephony(36),
* telefaxGroup2-3(37),
* telephony7kHz(38),
* euroFileTransfer(39),
* fileTransferAndAccessManagement(40),
* videoconference(41),
* audioGraphicConference(42)
*/
u_int8_t basic_service;
/*!
* \brief Invocation mode (When it should be delivered.) (Optional)
* \details
* deferred(0),
* immediate(1),
* combined(2)
*/
u_int8_t mode;
/*! \brief TRUE if NumberOfMessages present */
u_int8_t number_of_messages_present;
/*! \brief TRUE if time present */
u_int8_t time_present;
/*! \brief TRUE if MessageId present */
u_int8_t message_id_present;
/*! \brief TRUE if invocation mode present */
u_int8_t mode_present;
};
/*
* ARGUMENT SEQUENCE {
* receivingUserNr PartyNumber,
* basicService BasicService,
* controllingUserNr PartyNumber OPTIONAL,
* mode InvocationMode OPTIONAL
* }
*/
struct roseEtsiMWIDeactivate_ARG {
/*! \brief Receiving user number (Who the message is for.) */
struct rosePartyNumber receiving_user_number;
/*! \brief Controlling user number (Mailbox number) (Optional) */
struct rosePartyNumber controlling_user_number;
/*!
* \brief Type of call leaving message.
* \details
* allServices(0),
* speech(1),
* unrestrictedDigitalInformation(2),
* audio3k1Hz(3),
* unrestrictedDigitalInformationWithTonesAndAnnouncements(4),
* multirate(5),
* telephony3k1Hz(32),
* teletex(33),
* telefaxGroup4Class1(34),
* videotexSyntaxBased(35),
* videotelephony(36),
* telefaxGroup2-3(37),
* telephony7kHz(38),
* euroFileTransfer(39),
* fileTransferAndAccessManagement(40),
* videoconference(41),
* audioGraphicConference(42)
*/
u_int8_t basic_service;
/*!
* \brief Invocation mode (When it should be delivered.) (Optional)
* \details
* deferred(0),
* immediate(1),
* combined(2)
*/
u_int8_t mode;
/*! \brief TRUE if invocation mode present */
u_int8_t mode_present;
};
/*
* ARGUMENT SEQUENCE {
* controllingUserNr [1] EXPLICIT PartyNumber OPTIONAL,
* basicService [2] EXPLICIT BasicService OPTIONAL,
* numberOfMessages [3] EXPLICIT MessageCounter OPTIONAL,
* controllingUserProvidedNr [4] EXPLICIT PartyNumber OPTIONAL,
* time [5] EXPLICIT GeneralizedTime OPTIONAL,
* messageId [6] EXPLICIT MessageID OPTIONAL
* }
*/
struct roseEtsiMWIIndicate_ARG {
/*! \brief Number of messages in mailbox. (INTEGER (0..65535)) (Optional) */
u_int16_t number_of_messages;
/*! \brief Message ID (Status of this message) (Optional)*/
struct roseEtsiMessageID message_id;
/*! \brief Controlling user number (Mailbox number) (Optional) */
struct rosePartyNumber controlling_user_number;
/*! \brief Controlling user provided number (Caller-ID of party leaving message) (Optional) */
struct rosePartyNumber controlling_user_provided_number;
/*! \brief When message left. (optional) */
struct roseGeneralizedTime time;
/*!
* \brief Type of call leaving message.
* \details
* allServices(0),
* speech(1),
* unrestrictedDigitalInformation(2),
* audio3k1Hz(3),
* unrestrictedDigitalInformationWithTonesAndAnnouncements(4),
* multirate(5),
* telephony3k1Hz(32),
* teletex(33),
* telefaxGroup4Class1(34),
* videotexSyntaxBased(35),
* videotelephony(36),
* telefaxGroup2-3(37),
* telephony7kHz(38),
* euroFileTransfer(39),
* fileTransferAndAccessManagement(40),
* videoconference(41),
* audioGraphicConference(42)
*/
u_int8_t basic_service;
/*! \brief TRUE if basic_service present */
u_int8_t basic_service_present;
/*! \brief TRUE if NumberOfMessages present */
u_int8_t number_of_messages_present;
/*! \brief TRUE if time present */
u_int8_t time_present;
/*! \brief TRUE if MessageId present */
u_int8_t message_id_present;
};
/* ------------------------------------------------------------------- */
/*
* Name ::= CHOICE {
* -- iso8859-1 is implied in namePresentationAllowedSimple.
@@ -2835,6 +3484,146 @@ struct roseQsigDivertingLegInformation3_ARG {
/* ------------------------------------------------------------------- */
/*
* CcExtension ::= CHOICE {
* none NULL,
* single [14] IMPLICIT Extension,
* multiple [15] IMPLICIT SEQUENCE OF Extension
* }
*/
/*
* CcRequestArg ::= SEQUENCE {
* numberA PresentedNumberUnscreened,
* numberB PartyNumber,
*
* -- permitted information elements are:
* -- Bearer capability;
* -- Low layer compatibility;
* -- High layer compatibility
* service PSS1InformationElement,
* subaddrA [10] EXPLICIT PartySubaddress OPTIONAL,
* subaddrB [11] EXPLICIT PartySubaddress OPTIONAL,
* can-retain-service [12] IMPLICIT BOOLEAN DEFAULT FALSE,
*
* -- TRUE: signalling connection to be retained;
* -- FALSE: signalling connection to be released;
* -- omission: release or retain signalling connection
* retain-sig-connection [13] IMPLICIT BOOLEAN OPTIONAL,
* extension CcExtension OPTIONAL
* }
*/
struct roseQsigCcRequestArg {
struct rosePresentedNumberUnscreened number_a;
struct rosePartyNumber number_b;
/*!
* \brief subaddrA (optional)
* The subaddress is present if the length is nonzero.
*/
struct rosePartySubaddress subaddr_a;
/*!
* \brief subaddrB (optional)
* The subaddress is present if the length is nonzero.
*/
struct rosePartySubaddress subaddr_b;
/*!
* \brief The BC, HLC (optional) and LLC (optional) information.
* \note The ASN.1 field name is service.
*/
struct roseQ931ie q931ie;
/*! \brief q931ie.contents "allocated" after the stucture. */
unsigned char q931ie_contents[ROSE_Q931_MAX_BC + ROSE_Q931_MAX_HLC +
ROSE_Q931_MAX_LLC + 1];
/*! \brief TRUE if can retain service (DEFAULT FALSE) */
u_int8_t can_retain_service;
/*!
* \brief TRUE if retain_sig_connection present
* \note If not present then the signaling connection could be
* released or retained.
*/
u_int8_t retain_sig_connection_present;
/*!
* \brief Determine if the signalling connection should be retained.
* \note TRUE if signalling connection to be retained.
* \note FALSE if signalling connection to be released.
*/
u_int8_t retain_sig_connection;
};
/*
* CcRequestRes ::= SEQUENCE {
* no-path-reservation [0] IMPLICIT BOOLEAN DEFAULT FALSE,
* retain-service [1] IMPLICIT BOOLEAN DEFAULT FALSE,
* extension CcExtension OPTIONAL
* }
*/
struct roseQsigCcRequestRes {
/*! \brief TRUE if no path reservation. (DEFAULT FALSE) */
u_int8_t no_path_reservation;
/*! \brief TRUE if agree to retain service (DEFAULT FALSE) */
u_int8_t retain_service;
};
/*
* CcOptionalArg ::= CHOICE {
* fullArg [0] IMPLICIT SEQUENCE {
* numberA PartyNumber,
* numberB PartyNumber,
*
* -- permitted information elements are:
* -- Bearer capability;
* -- Low layer compatibility;
* -- High layer compatibility.
* service PSS1InformationElement,
* subaddrA [10] EXPLICIT PartySubaddress OPTIONAL,
* subaddrB [11] EXPLICIT PartySubaddress OPTIONAL,
* extension CcExtension OPTIONAL
* },
* extArg CcExtension
* }
*/
struct roseQsigCcOptionalArg {
#if 1 /* The conditional is here to indicate fullArg values grouping. */
struct rosePartyNumber number_a;
struct rosePartyNumber number_b;
/*!
* \brief subaddrA (optional)
* The subaddress is present if the length is nonzero.
*/
struct rosePartySubaddress subaddr_a;
/*!
* \brief subaddrB (optional)
* The subaddress is present if the length is nonzero.
*/
struct rosePartySubaddress subaddr_b;
/*!
* \brief The BC, HLC (optional) and LLC (optional) information.
* \note The ASN.1 field name is service.
*/
struct roseQ931ie q931ie;
/*! \brief q931ie.contents "allocated" after the stucture. */
unsigned char q931ie_contents[ROSE_Q931_MAX_BC + ROSE_Q931_MAX_HLC +
ROSE_Q931_MAX_LLC + 1];
#endif /* end fullArg values */
/*! \brief TRUE if the fullArg values are present. */
u_int8_t full_arg_present;
};
/* ------------------------------------------------------------------- */
/*
* MsgCentreId ::= CHOICE {
* integer [0] IMPLICIT INTEGER (0..65535),
@@ -2899,7 +3688,7 @@ struct roseQsigMWIActivateArg {
struct rosePartyNumber originating_number;
/*! \brief GeneralizedTime (SIZE (12..19)) (optional) */
unsigned char timestamp[19 + 1];
struct roseGeneralizedTime timestamp;
/*!
* \details
@@ -3124,7 +3913,7 @@ struct roseQsigMWIInterrogateResElt {
struct rosePartyNumber originating_number;
/*! \brief GeneralizedTime (SIZE (12..19)) (optional) */
unsigned char timestamp[19 + 1];
struct roseGeneralizedTime timestamp;
/*!
* \details
@@ -3283,6 +4072,39 @@ union rose_msg_invoke_etsi_args {
struct roseEtsiSubaddressTransfer_ARG SubaddressTransfer;
struct roseEtsiEctInform_ARG EctInform;
struct roseEtsiEctLoopTest_ARG EctLoopTest;
/* ETSI Status Request (CCBS/CCNR support) */
struct roseEtsiStatusRequest_ARG StatusRequest;
/* ETSI CCBS/CCNR support */
struct roseEtsiCallInfoRetain_ARG CallInfoRetain;
struct roseEtsiEraseCallLinkageID_ARG EraseCallLinkageID;
struct roseEtsiCCBSDeactivate_ARG CCBSDeactivate;
struct roseEtsiCCBSErase_ARG CCBSErase;
struct roseEtsiCCBSRemoteUserFree_ARG CCBSRemoteUserFree;
struct roseEtsiCCBSCall_ARG CCBSCall;
struct roseEtsiCCBSStatusRequest_ARG CCBSStatusRequest;
struct roseEtsiCCBSBFree_ARG CCBSBFree;
struct roseEtsiCCBSStopAlerting_ARG CCBSStopAlerting;
/* ETSI CCBS */
struct roseEtsiCCBSRequest_ARG CCBSRequest;
struct roseEtsiCCBSInterrogate_ARG CCBSInterrogate;
/* ETSI CCNR */
struct roseEtsiCCBSRequest_ARG CCNRRequest;
struct roseEtsiCCBSInterrogate_ARG CCNRInterrogate;
/* ETSI CCBS-T */
struct roseEtsiCCBS_T_Request_ARG CCBS_T_Request;
/* ETSI CCNR-T */
struct roseEtsiCCBS_T_Request_ARG CCNR_T_Request;
/* ETSI Message Waiting Indication (MWI) */
struct roseEtsiMWIActivate_ARG MWIActivate;
struct roseEtsiMWIDeactivate_ARG MWIDeactivate;
struct roseEtsiMWIIndicate_ARG MWIIndicate;
};
/*! \brief Facility ie result etsi messages with arguments. */
@@ -3297,6 +4119,26 @@ union rose_msg_result_etsi_args {
/* ETSI Explicit Call Transfer (ECT) */
struct roseEtsiEctLinkIdRequest_RES EctLinkIdRequest;
struct roseEtsiEctLoopTest_RES EctLoopTest;
/* ETSI Status Request (CCBS/CCNR support) */
struct roseEtsiStatusRequest_RES StatusRequest;
/* ETSI CCBS/CCNR support */
struct roseEtsiCCBSStatusRequest_RES CCBSStatusRequest;
/* ETSI CCBS */
struct roseEtsiCCBSRequest_RES CCBSRequest;
struct roseEtsiCCBSInterrogate_RES CCBSInterrogate;
/* ETSI CCNR */
struct roseEtsiCCBSRequest_RES CCNRRequest;
struct roseEtsiCCBSInterrogate_RES CCNRInterrogate;
/* ETSI CCBS-T */
struct roseEtsiCCBS_T_Request_RES CCBS_T_Request;
/* ETSI CCNR-T */
struct roseEtsiCCBS_T_Request_RES CCNR_T_Request;
};
/*! \brief Facility ie invoke qsig messages with arguments. */
@@ -3333,6 +4175,12 @@ union rose_msg_invoke_qsig_args {
struct roseQsigDivertingLegInformation2_ARG DivertingLegInformation2;
struct roseQsigDivertingLegInformation3_ARG DivertingLegInformation3;
/* Q.SIG SS-CC-Operations */
struct roseQsigCcRequestArg CcbsRequest;
struct roseQsigCcRequestArg CcnrRequest;
struct roseQsigCcOptionalArg CcCancel;
struct roseQsigCcOptionalArg CcExecPossible;
/* Q.SIG SS-MWI-Operations */
struct roseQsigMWIActivateArg MWIActivate;
struct roseQsigMWIDeactivateArg MWIDeactivate;
@@ -3351,6 +4199,10 @@ union rose_msg_result_qsig_args {
/* Q.SIG Call-Diversion-Operations */
struct roseQsigForwardingList InterrogateDiversionQ;
/* Q.SIG SS-CC-Operations */
struct roseQsigCcRequestRes CcbsRequest;
struct roseQsigCcRequestRes CcnrRequest;
/* Q.SIG SS-MWI-Operations */
struct roseQsigMWIInterrogateRes MWIInterrogate;
};

View File

@@ -623,8 +623,13 @@ unsigned char *rose_enc_etsi_AOCSCurrency_ARG(struct pri *ctrl, unsigned char *p
ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
break;
case 1: /* currency_info_list */
ASN1_CALL(pos, rose_enc_etsi_AOCSCurrencyInfoList(ctrl, pos, end,
ASN1_TAG_SEQUENCE, &args->etsi.AOCSCurrency.currency_info));
if (args->etsi.AOCSCurrency.currency_info.num_records) {
ASN1_CALL(pos, rose_enc_etsi_AOCSCurrencyInfoList(ctrl, pos, end,
ASN1_TAG_SEQUENCE, &args->etsi.AOCSCurrency.currency_info));
} else {
/* There were no records so encode as charge_not_available */
ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
}
break;
default:
ASN1_ENC_ERROR(ctrl, "Unknown AOCSCurrency type");

1853
rose_etsi_cc.c Normal file

File diff suppressed because it is too large Load Diff

686
rose_etsi_mwi.c Normal file
View File

@@ -0,0 +1,686 @@
/*
* libpri: An implementation of Primary Rate ISDN
*
* Copyright (C) 2010 Digium, Inc.
*
* Richard Mudgett <rmudgett@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*
* In addition, when this program is distributed with Asterisk in
* any form that would qualify as a 'combined work' or as a
* 'derivative work' (but not mere aggregation), you can redistribute
* and/or modify the combination under the terms of the license
* provided with that copy of Asterisk, instead of the license
* terms granted here.
*/
/*!
* \file
* \brief ROSE Message Waiting Indication (MWI) operations
*
* Message Waiting Indication (MWI) supplementary service EN 300 745-1
*
* \author Richard Mudgett <rmudgett@digium.com>
*/
#include "compat.h"
#include "libpri.h"
#include "pri_internal.h"
#include "rose.h"
#include "rose_internal.h"
#include "asn1.h"
/* ------------------------------------------------------------------- */
/*!
* \internal
* \brief Encode the MessageID type.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param msg_id
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
static unsigned char *rose_enc_etsi_message_id(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const struct roseEtsiMessageID *msg_id)
{
unsigned char *seq_len;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER, msg_id->reference_number));
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED, msg_id->status));
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Encode the MWIActivate invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_etsi_MWIActivate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
const struct roseEtsiMWIActivate_ARG *mwi_activate;
unsigned char *seq_len;
unsigned char *explicit_len;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
mwi_activate = &args->etsi.MWIActivate;
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
&mwi_activate->receiving_user_number));
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
mwi_activate->basic_service));
if (mwi_activate->controlling_user_number.length) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
&mwi_activate->controlling_user_number));
ASN1_CONSTRUCTED_END(explicit_len, pos, end);
}
if (mwi_activate->number_of_messages_present) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
mwi_activate->number_of_messages));
ASN1_CONSTRUCTED_END(explicit_len, pos, end);
}
if (mwi_activate->controlling_user_provided_number.length) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
&mwi_activate->controlling_user_provided_number));
ASN1_CONSTRUCTED_END(explicit_len, pos, end);
}
if (mwi_activate->time_present) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4);
ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_GENERALIZED_TIME,
mwi_activate->time.str, sizeof(mwi_activate->time.str) - 1));
ASN1_CONSTRUCTED_END(explicit_len, pos, end);
}
if (mwi_activate->message_id_present) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 5);
ASN1_CALL(pos, rose_enc_etsi_message_id(ctrl, pos, end,
&mwi_activate->message_id));
ASN1_CONSTRUCTED_END(explicit_len, pos, end);
}
if (mwi_activate->mode_present) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 6);
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
mwi_activate->mode));
ASN1_CONSTRUCTED_END(explicit_len, pos, end);
}
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Encode the MWIDeactivate invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_etsi_MWIDeactivate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
const struct roseEtsiMWIDeactivate_ARG *mwi_deactivate;
unsigned char *seq_len;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
mwi_deactivate = &args->etsi.MWIDeactivate;
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
&mwi_deactivate->receiving_user_number));
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
mwi_deactivate->basic_service));
if (mwi_deactivate->controlling_user_number.length) {
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
&mwi_deactivate->controlling_user_number));
}
if (mwi_deactivate->mode_present) {
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
mwi_deactivate->mode));
}
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Encode the MWIIndicate invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_etsi_MWIIndicate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
const struct roseEtsiMWIIndicate_ARG *mwi_indicate;
unsigned char *seq_len;
unsigned char *explicit_len;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
mwi_indicate = &args->etsi.MWIIndicate;
if (mwi_indicate->controlling_user_number.length) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
&mwi_indicate->controlling_user_number));
ASN1_CONSTRUCTED_END(explicit_len, pos, end);
}
if (mwi_indicate->basic_service_present) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
mwi_indicate->basic_service));
ASN1_CONSTRUCTED_END(explicit_len, pos, end);
}
if (mwi_indicate->number_of_messages_present) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
mwi_indicate->number_of_messages));
ASN1_CONSTRUCTED_END(explicit_len, pos, end);
}
if (mwi_indicate->controlling_user_provided_number.length) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4);
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
&mwi_indicate->controlling_user_provided_number));
ASN1_CONSTRUCTED_END(explicit_len, pos, end);
}
if (mwi_indicate->time_present) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 5);
ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_GENERALIZED_TIME,
mwi_indicate->time.str, sizeof(mwi_indicate->time.str) - 1));
ASN1_CONSTRUCTED_END(explicit_len, pos, end);
}
if (mwi_indicate->message_id_present) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 6);
ASN1_CALL(pos, rose_enc_etsi_message_id(ctrl, pos, end,
&mwi_indicate->message_id));
ASN1_CONSTRUCTED_END(explicit_len, pos, end);
}
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \internal
* \brief Decode the MessageID argument parameters.
*
* \param ctrl D channel controller for any diagnostic messages.
* \param name Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param msg_id Parameter storage to fill.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
static const unsigned char *rose_dec_etsi_message_id(struct pri *ctrl, const char *name,
unsigned tag, const unsigned char *pos, const unsigned char *end,
struct roseEtsiMessageID *msg_id)
{
int32_t value;
int length;
int seq_offset;
const unsigned char *seq_end;
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %s MessageID %s\n", name, asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
ASN1_CALL(pos, asn1_dec_int(ctrl, "messageRef", tag, pos, seq_end, &value));
msg_id->reference_number = value;
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
ASN1_CALL(pos, asn1_dec_int(ctrl, "status", tag, pos, seq_end, &value));
msg_id->status = value;
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the MWIActivate invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_etsi_MWIActivate_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args)
{
int32_t value;
size_t str_len;
int length;
int seq_offset;
int explicit_offset;
const unsigned char *explicit_end;
const unsigned char *seq_end;
const unsigned char *save_pos;
struct roseEtsiMWIActivate_ARG *mwi_activate;
mwi_activate = &args->etsi.MWIActivate;
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " MWIActivate %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "receivingUserNr", tag, pos, seq_end,
&mwi_activate->receiving_user_number));
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
mwi_activate->basic_service = value;
/*
* A sequence specifies an ordered list of component types.
* However, for simplicity we are not checking the order of
* the remaining optional components.
*/
mwi_activate->controlling_user_number.length = 0;
mwi_activate->number_of_messages_present = 0;
mwi_activate->controlling_user_provided_number.length = 0;
mwi_activate->time_present = 0;
mwi_activate->message_id_present = 0;
mwi_activate->mode_present = 0;
while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
save_pos = pos;
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
switch (tag) {
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "controllingUserNr", tag, pos,
explicit_end, &mwi_activate->controlling_user_number));
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
ASN1_CALL(pos, asn1_dec_int(ctrl, "numberOfMessages", tag, pos, explicit_end,
&value));
mwi_activate->number_of_messages = value;
mwi_activate->number_of_messages_present = 1;
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "controllingUserProvidedNr", tag,
pos, explicit_end, &mwi_activate->controlling_user_provided_number));
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 4:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_TYPE_GENERALIZED_TIME);
ASN1_CALL(pos, asn1_dec_string_max(ctrl, "time", tag, pos, explicit_end,
sizeof(mwi_activate->time.str), mwi_activate->time.str, &str_len));
mwi_activate->time_present = 1;
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 5:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CALL(pos, rose_dec_etsi_message_id(ctrl, "messageId", tag, pos,
explicit_end, &mwi_activate->message_id));
mwi_activate->message_id_present = 1;
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 6:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
ASN1_CALL(pos, asn1_dec_int(ctrl, "mode", tag, pos, explicit_end, &value));
mwi_activate->mode = value;
mwi_activate->mode_present = 1;
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
default:
pos = save_pos;
goto cancel_options;
}
}
cancel_options:;
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the MWIDeactivate invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_etsi_MWIDeactivate_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args)
{
int32_t value;
int length;
int seq_offset;
const unsigned char *seq_end;
struct roseEtsiMWIDeactivate_ARG *mwi_deactivate;
mwi_deactivate = &args->etsi.MWIDeactivate;
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " MWIDeactivate %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "receivingUserNr", tag, pos, seq_end,
&mwi_deactivate->receiving_user_number));
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
mwi_deactivate->basic_service = value;
/*
* A sequence specifies an ordered list of component types.
* However, for simplicity we are not checking the order of
* the remaining optional components.
*/
mwi_deactivate->controlling_user_number.length = 0;
mwi_deactivate->mode_present = 0;
while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
switch (tag) {
default:
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "controllingUserNr", tag, pos,
seq_end, &mwi_deactivate->controlling_user_number));
break;
case ASN1_TYPE_ENUMERATED:
ASN1_CALL(pos, asn1_dec_int(ctrl, "mode", tag, pos, seq_end, &value));
mwi_deactivate->mode = value;
mwi_deactivate->mode_present = 1;
break;
}
}
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the MWIIndicate invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_etsi_MWIIndicate_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args)
{
int32_t value;
size_t str_len;
int length;
int seq_offset;
int explicit_offset;
const unsigned char *explicit_end;
const unsigned char *seq_end;
const unsigned char *save_pos;
struct roseEtsiMWIIndicate_ARG *mwi_indicate;
mwi_indicate = &args->etsi.MWIIndicate;
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " MWIIndicate %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
/*
* A sequence specifies an ordered list of component types.
* However, for simplicity we are not checking the order of
* the remaining optional components.
*/
mwi_indicate->controlling_user_number.length = 0;
mwi_indicate->basic_service_present = 0;
mwi_indicate->number_of_messages_present = 0;
mwi_indicate->controlling_user_provided_number.length = 0;
mwi_indicate->time_present = 0;
mwi_indicate->message_id_present = 0;
while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
save_pos = pos;
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
switch (tag) {
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "controllingUserNr", tag, pos,
explicit_end, &mwi_indicate->controlling_user_number));
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, explicit_end,
&value));
mwi_indicate->basic_service = value;
mwi_indicate->basic_service_present = 1;
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
ASN1_CALL(pos, asn1_dec_int(ctrl, "numberOfMessages", tag, pos, explicit_end,
&value));
mwi_indicate->number_of_messages = value;
mwi_indicate->number_of_messages_present = 1;
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 4:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "controllingUserProvidedNr", tag,
pos, explicit_end, &mwi_indicate->controlling_user_provided_number));
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 5:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_TYPE_GENERALIZED_TIME);
ASN1_CALL(pos, asn1_dec_string_max(ctrl, "time", tag, pos, explicit_end,
sizeof(mwi_indicate->time.str), mwi_indicate->time.str, &str_len));
mwi_indicate->time_present = 1;
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 6:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CALL(pos, rose_dec_etsi_message_id(ctrl, "messageId", tag, pos,
explicit_end, &mwi_indicate->message_id));
mwi_indicate->message_id_present = 1;
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
default:
pos = save_pos;
goto cancel_options;
}
}
cancel_options:;
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/* ------------------------------------------------------------------- */
/* end rose_etsi_mwi.c */

View File

@@ -238,6 +238,153 @@ const unsigned char *rose_dec_etsi_EctLoopTest_RES(struct pri *ctrl, unsigned ta
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
/* ETSI Status Request */
unsigned char *rose_enc_etsi_StatusRequest_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_StatusRequest_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
const unsigned char *rose_dec_etsi_StatusRequest_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_StatusRequest_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
/* ETSI Call-Completion Busy Status (CCBS) / Call-Completion No Reply (CCNR) */
unsigned char *rose_enc_etsi_CallInfoRetain_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_EraseCallLinkageID_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CCBSDeactivate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CCBSErase_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CCBSRemoteUserFree_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CCBSCall_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CCBSBFree_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CCBSStopAlerting_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CCBSStatusRequest_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CCBSStatusRequest_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
unsigned char *rose_enc_etsi_CCBSRequest_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CCNRRequest_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CCBSRequest_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
unsigned char *rose_enc_etsi_CCNRRequest_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
unsigned char *rose_enc_etsi_CCBSInterrogate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CCNRInterrogate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CCBSInterrogate_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
unsigned char *rose_enc_etsi_CCNRInterrogate_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
const unsigned char *rose_dec_etsi_CallInfoRetain_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_EraseCallLinkageID_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CCBSDeactivate_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CCBSErase_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CCBSRemoteUserFree_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CCBSCall_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CCBSBFree_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CCBSStopAlerting_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CCBSStatusRequest_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CCBSStatusRequest_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
const unsigned char *rose_dec_etsi_CCBSRequest_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CCNRRequest_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CCBSRequest_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
const unsigned char *rose_dec_etsi_CCNRRequest_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
const unsigned char *rose_dec_etsi_CCBSInterrogate_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CCNRInterrogate_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CCBSInterrogate_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
const unsigned char *rose_dec_etsi_CCNRInterrogate_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
/* ETSI CCBS-T/CCNR-T */
unsigned char *rose_enc_etsi_CCBS_T_Request_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CCNR_T_Request_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CCBS_T_Request_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
unsigned char *rose_enc_etsi_CCNR_T_Request_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
const unsigned char *rose_dec_etsi_CCBS_T_Request_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CCNR_T_Request_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CCBS_T_Request_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
const unsigned char *rose_dec_etsi_CCNR_T_Request_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
/* ETSI Message Waiting Indication (MWI) */
unsigned char *rose_enc_etsi_MWIActivate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_MWIDeactivate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_MWIIndicate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_MWIActivate_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_MWIDeactivate_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_MWIIndicate_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
/* Q.SIG Name-Operations */
unsigned char *rose_enc_qsig_Name(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const struct roseQsigName *name);
@@ -416,6 +563,64 @@ const unsigned char *rose_dec_qsig_SubaddressTransfer_ARG(struct pri *ctrl, unsi
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
/* Q.SIG SS-CC-Operations */
unsigned char *rose_enc_qsig_CcbsRequest_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_CcnrRequest_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_CcbsRequest_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
unsigned char *rose_enc_qsig_CcnrRequest_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
unsigned char *rose_enq_qsig_CcCancel_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enq_qsig_CcExecPossible_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_CcPathReserve_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_CcPathReserve_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
unsigned char *rose_enc_qsig_CcRingout_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_CcSuspend_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_CcResume_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_CcbsRequest_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_CcnrRequest_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_CcbsRequest_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
const unsigned char *rose_dec_qsig_CcnrRequest_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
const unsigned char *rose_dec_qsig_CcCancel_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_CcExecPossible_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_CcPathReserve_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_CcPathReserve_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
const unsigned char *rose_dec_qsig_CcRingout_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_CcSuspend_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_CcResume_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
/* Q.SIG SS-MWI-Operations */
unsigned char *rose_enc_qsig_MWIActivate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);

984
rose_qsig_cc.c Normal file
View File

@@ -0,0 +1,984 @@
/*
* libpri: An implementation of Primary Rate ISDN
*
* Copyright (C) 2009 Digium, Inc.
*
* Richard Mudgett <rmudgett@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*
* In addition, when this program is distributed with Asterisk in
* any form that would qualify as a 'combined work' or as a
* 'derivative work' (but not mere aggregation), you can redistribute
* and/or modify the combination under the terms of the license
* provided with that copy of Asterisk, instead of the license
* terms granted here.
*/
/*!
* \file
* \brief Q.SIG ROSE SS-CC-Operations (CC)
*
* SS-CC-Operations ECMA-186 Annex F Table F.1
*
* \author Richard Mudgett <rmudgett@digium.com>
*/
#include "compat.h"
#include "libpri.h"
#include "pri_internal.h"
#include "rose.h"
#include "rose_internal.h"
#include "asn1.h"
/* ------------------------------------------------------------------- */
/*!
* \internal
* \brief Encode the CcExtension type.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*
* \details
* CcExtension ::= CHOICE {
* none NULL,
* single [14] IMPLICIT Extension,
* multiple [15] IMPLICIT SEQUENCE OF Extension
* }
*/
static unsigned char *rose_enc_qsig_CcExtension(struct pri *ctrl, unsigned char *pos,
unsigned char *end)
{
return asn1_enc_null(pos, end, ASN1_TYPE_NULL);
}
/*!
* \internal
* \brief Encode the CcRequestArg type.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param tag Component tag to identify the encoded component.
* The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
* tags it otherwise.
* \param cc_request_arg Call-completion request arguments to encode.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
static unsigned char *rose_enc_qsig_CcRequestArg(struct pri *ctrl, unsigned char *pos,
unsigned char *end, unsigned tag, const struct roseQsigCcRequestArg *cc_request_arg)
{
unsigned char *seq_len;
unsigned char *exp_len;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
ASN1_CALL(pos, rose_enc_PresentedNumberUnscreened(ctrl, pos, end,
&cc_request_arg->number_a));
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &cc_request_arg->number_b));
ASN1_CALL(pos, rose_enc_Q931ie(ctrl, pos, end, ASN1_CLASS_APPLICATION | 0,
&cc_request_arg->q931ie));
if (cc_request_arg->subaddr_a.length) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 10);
ASN1_CALL(pos, rose_enc_PartySubaddress(ctrl, pos, end,
&cc_request_arg->subaddr_a));
ASN1_CONSTRUCTED_END(exp_len, pos, end);
}
if (cc_request_arg->subaddr_b.length) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 11);
ASN1_CALL(pos, rose_enc_PartySubaddress(ctrl, pos, end,
&cc_request_arg->subaddr_b));
ASN1_CONSTRUCTED_END(exp_len, pos, end);
}
if (cc_request_arg->can_retain_service) {
/* Not the DEFAULT value */
ASN1_CALL(pos, asn1_enc_boolean(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 12,
cc_request_arg->can_retain_service));
}
if (cc_request_arg->retain_sig_connection_present) {
ASN1_CALL(pos, asn1_enc_boolean(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 13,
cc_request_arg->retain_sig_connection));
}
/* No extension to encode */
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Encode the Q.SIG CcbsRequest invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_CcbsRequest_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
return rose_enc_qsig_CcRequestArg(ctrl, pos, end, ASN1_TAG_SEQUENCE,
&args->qsig.CcbsRequest);
}
/*!
* \brief Encode the Q.SIG CcnrRequest invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_CcnrRequest_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
return rose_enc_qsig_CcRequestArg(ctrl, pos, end, ASN1_TAG_SEQUENCE,
&args->qsig.CcnrRequest);
}
/*!
* \internal
* \brief Encode the CcRequestRes type.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param tag Component tag to identify the encoded component.
* The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
* tags it otherwise.
* \param cc_request_res Call-completion request result to encode.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
static unsigned char *rose_enc_qsig_CcRequestRes(struct pri *ctrl, unsigned char *pos,
unsigned char *end, unsigned tag, const struct roseQsigCcRequestRes *cc_request_res)
{
unsigned char *seq_len;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
if (cc_request_res->no_path_reservation) {
/* Not the DEFAULT value */
ASN1_CALL(pos, asn1_enc_boolean(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
cc_request_res->no_path_reservation));
}
if (cc_request_res->retain_service) {
/* Not the DEFAULT value */
ASN1_CALL(pos, asn1_enc_boolean(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
cc_request_res->retain_service));
}
/* No extension to encode */
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Encode the Q.SIG CcbsRequest result facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_CcbsRequest_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args)
{
return rose_enc_qsig_CcRequestRes(ctrl, pos, end, ASN1_TAG_SEQUENCE,
&args->qsig.CcbsRequest);
}
/*!
* \brief Encode the Q.SIG CcnrRequest result facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_CcnrRequest_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args)
{
return rose_enc_qsig_CcRequestRes(ctrl, pos, end, ASN1_TAG_SEQUENCE,
&args->qsig.CcnrRequest);
}
/*!
* \internal
* \brief Encode the CcOptionalArg type.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param cc_optional_arg Call-completion optional arguments to encode.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
static unsigned char *rose_enc_qsig_CcOptionalArg(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const struct roseQsigCcOptionalArg *cc_optional_arg)
{
unsigned char *seq_len;
unsigned char *exp_len;
if (!cc_optional_arg->full_arg_present) {
return rose_enc_qsig_CcExtension(ctrl, pos, end);
}
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0);
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &cc_optional_arg->number_a));
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &cc_optional_arg->number_b));
ASN1_CALL(pos, rose_enc_Q931ie(ctrl, pos, end, ASN1_CLASS_APPLICATION | 0,
&cc_optional_arg->q931ie));
if (cc_optional_arg->subaddr_a.length) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 10);
ASN1_CALL(pos, rose_enc_PartySubaddress(ctrl, pos, end,
&cc_optional_arg->subaddr_a));
ASN1_CONSTRUCTED_END(exp_len, pos, end);
}
if (cc_optional_arg->subaddr_b.length) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 11);
ASN1_CALL(pos, rose_enc_PartySubaddress(ctrl, pos, end,
&cc_optional_arg->subaddr_b));
ASN1_CONSTRUCTED_END(exp_len, pos, end);
}
/* No extension to encode */
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Encode the Q.SIG CcCancel invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enq_qsig_CcCancel_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
return rose_enc_qsig_CcOptionalArg(ctrl, pos, end, &args->qsig.CcCancel);
}
/*!
* \brief Encode the Q.SIG CcExecPossible invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enq_qsig_CcExecPossible_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
return rose_enc_qsig_CcOptionalArg(ctrl, pos, end, &args->qsig.CcExecPossible);
}
/*!
* \brief Encode the Q.SIG CcPathReserve invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_CcPathReserve_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
return rose_enc_qsig_CcExtension(ctrl, pos, end);
}
/*!
* \brief Encode the Q.SIG CcPathReserve result facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_CcPathReserve_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args)
{
return rose_enc_qsig_CcExtension(ctrl, pos, end);
}
/*!
* \brief Encode the Q.SIG CcRingout invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_CcRingout_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
return rose_enc_qsig_CcExtension(ctrl, pos, end);
}
/*!
* \brief Encode the Q.SIG CcSuspend invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_CcSuspend_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
return rose_enc_qsig_CcExtension(ctrl, pos, end);
}
/*!
* \brief Encode the Q.SIG CcResume invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_CcResume_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
return rose_enc_qsig_CcExtension(ctrl, pos, end);
}
/*!
* \internal
* \brief Decode the CcExtension argument parameters.
*
* \param ctrl D channel controller for any diagnostic messages.
* \param name Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*
* \details
* CcExtension ::= CHOICE {
* none NULL,
* single [14] IMPLICIT Extension,
* multiple [15] IMPLICIT SEQUENCE OF Extension
* }
*/
static const unsigned char *rose_dec_qsig_CcExtension(struct pri *ctrl, const char *name,
unsigned tag, const unsigned char *pos, const unsigned char *end)
{
int length;
int ext_offset;
const unsigned char *ext_end;
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %s CcExtension\n", name);
}
switch (tag & ~ASN1_PC_MASK) {
case ASN1_TYPE_NULL:
/* Must not be constructed but we will not check for it for simplicity. */
return asn1_dec_null(ctrl, "none", tag, pos, end);
case ASN1_CLASS_CONTEXT_SPECIFIC | 14:
name = "single";
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 15:
name = "multiple";
break;
default:
ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
return NULL;
}
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %s %s\n", name, asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(ext_end, ext_offset, length, pos, end);
/* Fixup will skip over the manufacturer extension information */
ASN1_END_FIXUP(ctrl, pos, ext_offset, ext_end, end);
return pos;
}
/*!
* \internal
* \brief Decode the CcRequestArg argument parameters.
*
* \param ctrl D channel controller for any diagnostic messages.
* \param name Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param cc_request_arg Parameter storage to fill.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
static const unsigned char *rose_dec_qsig_CcRequestArg(struct pri *ctrl,
const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
struct roseQsigCcRequestArg *cc_request_arg)
{
int32_t value;
int length;
int seq_offset;
int explicit_offset;
const unsigned char *explicit_end;
const unsigned char *seq_end;
const unsigned char *save_pos;
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %s CcRequestArg %s\n", name, asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CALL(pos, rose_dec_PresentedNumberUnscreened(ctrl, "numberA", tag, pos, seq_end,
&cc_request_arg->number_a));
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "numberB", tag, pos, seq_end,
&cc_request_arg->number_b));
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag & ~ASN1_PC_MASK, ASN1_CLASS_APPLICATION | 0);
ASN1_CALL(pos, rose_dec_Q931ie(ctrl, "service", tag, pos, seq_end,
&cc_request_arg->q931ie, sizeof(cc_request_arg->q931ie_contents)));
/*
* A sequence specifies an ordered list of component types.
* However, for simplicity we are not checking the order of
* the remaining optional components.
*/
cc_request_arg->subaddr_a.length = 0;
cc_request_arg->subaddr_b.length = 0;
cc_request_arg->can_retain_service = 0; /* DEFAULT FALSE */
cc_request_arg->retain_sig_connection_present = 0;
while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
save_pos = pos;
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
switch (tag) {
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 10:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CALL(pos, rose_dec_PartySubaddress(ctrl, "subaddrA", tag, pos,
explicit_end, &cc_request_arg->subaddr_a));
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 11:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CALL(pos, rose_dec_PartySubaddress(ctrl, "subaddrB", tag, pos,
explicit_end, &cc_request_arg->subaddr_b));
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 12:
ASN1_CALL(pos, asn1_dec_boolean(ctrl, "can-retain-service", tag, pos,
seq_end, &value));
cc_request_arg->can_retain_service = value;
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 13:
ASN1_CALL(pos, asn1_dec_boolean(ctrl, "retain-sig-connection", tag, pos,
seq_end, &value));
cc_request_arg->retain_sig_connection = value;
cc_request_arg->retain_sig_connection_present = 1;
break;
case ASN1_TYPE_NULL:
case ASN1_CLASS_CONTEXT_SPECIFIC | 14:
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 14:
case ASN1_CLASS_CONTEXT_SPECIFIC | 15:
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 15:
ASN1_CALL(pos, rose_dec_qsig_CcExtension(ctrl, "extension", tag, pos,
seq_end));
break;
default:
pos = save_pos;
goto cancel_options;
}
}
cancel_options:;
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the Q.SIG CcbsRequest invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CcbsRequest_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
return rose_dec_qsig_CcRequestArg(ctrl, "CcbsRequest", tag, pos, end,
&args->qsig.CcbsRequest);
}
/*!
* \brief Decode the Q.SIG CcnrRequest invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CcnrRequest_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
return rose_dec_qsig_CcRequestArg(ctrl, "CcnrRequest", tag, pos, end,
&args->qsig.CcnrRequest);
}
/*!
* \internal
* \brief Decode the CcRequestRes argument parameters.
*
* \param ctrl D channel controller for any diagnostic messages.
* \param name Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param cc_request_res Parameter storage to fill.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
static const unsigned char *rose_dec_qsig_CcRequestRes(struct pri *ctrl,
const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
struct roseQsigCcRequestRes *cc_request_res)
{
int32_t value;
int length;
int seq_offset;
const unsigned char *seq_end;
const unsigned char *save_pos;
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %s CcRequestRes %s\n", name, asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
/*
* A sequence specifies an ordered list of component types.
* However, for simplicity we are not checking the order of
* the remaining optional components.
*/
cc_request_res->no_path_reservation = 0; /* DEFAULT FALSE */
cc_request_res->retain_service = 0; /* DEFAULT FALSE */
while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
save_pos = pos;
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
switch (tag) {
case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
ASN1_CALL(pos, asn1_dec_boolean(ctrl, "no-path-reservation", tag, pos,
seq_end, &value));
cc_request_res->no_path_reservation = value;
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
ASN1_CALL(pos, asn1_dec_boolean(ctrl, "retain-service", tag, pos, seq_end,
&value));
cc_request_res->retain_service = value;
break;
case ASN1_TYPE_NULL:
case ASN1_CLASS_CONTEXT_SPECIFIC | 14:
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 14:
case ASN1_CLASS_CONTEXT_SPECIFIC | 15:
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 15:
ASN1_CALL(pos, rose_dec_qsig_CcExtension(ctrl, "extension", tag, pos,
seq_end));
break;
default:
pos = save_pos;
goto cancel_options;
}
}
cancel_options:;
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the Q.SIG CcbsRequest result argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CcbsRequest_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
{
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
return rose_dec_qsig_CcRequestRes(ctrl, "CcbsRequest", tag, pos, end,
&args->qsig.CcbsRequest);
}
/*!
* \brief Decode the Q.SIG CcnrRequest result argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CcnrRequest_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
{
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
return rose_dec_qsig_CcRequestRes(ctrl, "CcnrRequest", tag, pos, end,
&args->qsig.CcnrRequest);
}
/*!
* \internal
* \brief Decode the CcOptionalArg argument parameters.
*
* \param ctrl D channel controller for any diagnostic messages.
* \param name Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param cc_optional_arg Parameter storage to fill.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
static const unsigned char *rose_dec_qsig_CcOptionalArg(struct pri *ctrl,
const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
struct roseQsigCcOptionalArg *cc_optional_arg)
{
int length;
int seq_offset;
int explicit_offset;
const unsigned char *explicit_end;
const unsigned char *seq_end;
const unsigned char *save_pos;
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %s CcOptionalArg\n", name);
}
if (tag != (ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0)) {
cc_optional_arg->full_arg_present = 0;
return rose_dec_qsig_CcExtension(ctrl, "extArg", tag, pos, end);
}
cc_optional_arg->full_arg_present = 1;
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " fullArg %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "numberA", tag, pos, seq_end,
&cc_optional_arg->number_a));
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "numberB", tag, pos, seq_end,
&cc_optional_arg->number_b));
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag & ~ASN1_PC_MASK, ASN1_CLASS_APPLICATION | 0);
ASN1_CALL(pos, rose_dec_Q931ie(ctrl, "service", tag, pos, seq_end,
&cc_optional_arg->q931ie, sizeof(cc_optional_arg->q931ie_contents)));
/*
* A sequence specifies an ordered list of component types.
* However, for simplicity we are not checking the order of
* the remaining optional components.
*/
cc_optional_arg->subaddr_a.length = 0;
cc_optional_arg->subaddr_b.length = 0;
while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
save_pos = pos;
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
switch (tag) {
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 10:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CALL(pos, rose_dec_PartySubaddress(ctrl, "subaddrA", tag, pos,
explicit_end, &cc_optional_arg->subaddr_a));
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 11:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CALL(pos, rose_dec_PartySubaddress(ctrl, "subaddrB", tag, pos,
explicit_end, &cc_optional_arg->subaddr_b));
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_TYPE_NULL:
case ASN1_CLASS_CONTEXT_SPECIFIC | 14:
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 14:
case ASN1_CLASS_CONTEXT_SPECIFIC | 15:
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 15:
ASN1_CALL(pos, rose_dec_qsig_CcExtension(ctrl, "extension", tag, pos,
seq_end));
break;
default:
pos = save_pos;
goto cancel_options;
}
}
cancel_options:;
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the Q.SIG CcCancel invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CcCancel_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
return rose_dec_qsig_CcOptionalArg(ctrl, "CcCancel", tag, pos, end,
&args->qsig.CcCancel);
}
/*!
* \brief Decode the Q.SIG CcExecPossible invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CcExecPossible_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
return rose_dec_qsig_CcOptionalArg(ctrl, "CcExecPossible", tag, pos, end,
&args->qsig.CcCancel);
}
/*!
* \brief Decode the Q.SIG CcPathReserve invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CcPathReserve_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
return rose_dec_qsig_CcExtension(ctrl, "CcPathReserve", tag, pos, end);
}
/*!
* \brief Decode the Q.SIG CcPathReserve result argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CcPathReserve_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
{
return rose_dec_qsig_CcExtension(ctrl, "CcPathReserve", tag, pos, end);
}
/*!
* \brief Decode the Q.SIG CcRingout invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CcRingout_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
return rose_dec_qsig_CcExtension(ctrl, "CcRingout", tag, pos, end);
}
/*!
* \brief Decode the Q.SIG CcSuspend invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CcSuspend_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
return rose_dec_qsig_CcExtension(ctrl, "CcSuspend", tag, pos, end);
}
/*!
* \brief Decode the Q.SIG CcResume invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CcResume_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
return rose_dec_qsig_CcExtension(ctrl, "CcResume", tag, pos, end);
}
/* ------------------------------------------------------------------- */
/* end rose_qsig_cc.c */

View File

@@ -126,7 +126,7 @@ unsigned char *rose_enc_qsig_MWIActivate_ARG(struct pri *ctrl, unsigned char *po
}
if (mwi_activate->timestamp_present) {
ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_GENERALIZED_TIME,
mwi_activate->timestamp, sizeof(mwi_activate->timestamp) - 1));
mwi_activate->timestamp.str, sizeof(mwi_activate->timestamp.str) - 1));
}
if (mwi_activate->priority_present) {
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 5,
@@ -254,7 +254,7 @@ static unsigned char *rose_enc_qsig_MWIInterrogateResElt(struct pri *ctrl,
}
if (record->timestamp_present) {
ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_GENERALIZED_TIME,
record->timestamp, sizeof(record->timestamp) - 1));
record->timestamp.str, sizeof(record->timestamp.str) - 1));
}
if (record->priority_present) {
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 5,
@@ -450,7 +450,8 @@ const unsigned char *rose_dec_qsig_MWIActivate_ARG(struct pri *ctrl, unsigned ta
break;
case ASN1_TYPE_GENERALIZED_TIME:
ASN1_CALL(pos, asn1_dec_string_max(ctrl, "timestamp", tag, pos, end,
sizeof(mwi_activate->timestamp), mwi_activate->timestamp, &str_len));
sizeof(mwi_activate->timestamp.str), mwi_activate->timestamp.str,
&str_len));
mwi_activate->timestamp_present = 1;
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 5:
@@ -710,7 +711,7 @@ static const unsigned char *rose_dec_qsig_MWIInterrogateResElt(struct pri *ctrl,
break;
case ASN1_TYPE_GENERALIZED_TIME:
ASN1_CALL(pos, asn1_dec_string_max(ctrl, "timestamp", tag, pos, end,
sizeof(record->timestamp), record->timestamp, &str_len));
sizeof(record->timestamp.str), record->timestamp.str, &str_len));
record->timestamp_present = 1;
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 5:

View File

@@ -382,6 +382,7 @@ static const unsigned char *rose_dec_qsig_PartyName_ARG_Backend(struct pri *ctrl
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CALL(pos, rose_dec_qsig_Name(ctrl, "name", tag, pos, seq_end,
&party->name));

File diff suppressed because it is too large Load Diff