Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
271a4f3067 | ||
|
|
64ae283190 | ||
|
|
692697d39b | ||
|
|
9a7715a09d | ||
|
|
a9696d095c | ||
|
|
ea9b8059de | ||
|
|
ee25bdfb5e | ||
|
|
2fd3fff781 | ||
|
|
1b11116f18 | ||
|
|
52c6b7289d | ||
|
|
3cb1f6fbce | ||
|
|
2ab04a7663 | ||
|
|
915d423ffc | ||
|
|
a3a73a30c9 | ||
|
|
c286f741be | ||
|
|
183cd86a8d | ||
|
|
c955ba2510 | ||
|
|
a0c05f9908 | ||
|
|
9b5066cc78 | ||
|
|
9648194287 | ||
|
|
ff36053fdd | ||
|
|
d9276a9c5e | ||
|
|
c3cc1ed5b0 | ||
|
|
cd8d727df8 | ||
|
|
4e591eb689 | ||
|
|
eb0586daa1 |
277
ChangeLog
277
ChangeLog
@@ -1,3 +1,280 @@
|
||||
2010-11-17 Leif Madsen <lmadsen@digium.com>
|
||||
|
||||
* libpri 1.4.11.5 released.
|
||||
|
||||
2010-11-17 21:32 +0000 [r2131-2139] Richard Mudgett <rmudgett@digium.com>
|
||||
|
||||
* q921.c: Merged revision 2101 from
|
||||
https://origsvn.digium.com/svn/libpri/branches/1.4 ..........
|
||||
r2101 | rmudgett | 2010-11-05 14:24:01 -0500 (Fri, 05 Nov 2010) |
|
||||
9 lines Remove all TEIs when NT PTMP starts. Remove all TEIs when
|
||||
a NT PTMP link is started and there are no other links to make
|
||||
sure there are no devices that think they have a TEI. A device
|
||||
may think it has a TEI if the upper layer program is restarted or
|
||||
the system reboots. This fixes the bug portion of JIRA
|
||||
LIBPRI-51/SWP-2453. ..........
|
||||
|
||||
* q921.c: Merged revision 2088 from
|
||||
https://origsvn.digium.com/svn/libpri/branches/1.4 ..........
|
||||
r2088 | rmudgett | 2010-11-02 14:11:01 -0500 (Tue, 02 Nov 2010) |
|
||||
14 lines B410P gets incoming call packets on ISDN but Asterisk
|
||||
doesn't see the call. The Cisco 1751 with VIC 2-BRI ports sends
|
||||
out SETUP messages on the broadcast TEI as if the BRI were PTMP
|
||||
even though it is configured for PTP mode. Make PTP mode also
|
||||
accept frames on SAPI=0, TEI=127 (Broadcast). (closes issue
|
||||
#18232) Reported by: lelio Patches: issue18232_v1.4.patch
|
||||
uploaded by rmudgett (license 664) Tested by: lelio ..........
|
||||
|
||||
* q931.c: Merged revision 2021 from
|
||||
https://origsvn.digium.com/svn/libpri/branches/1.4 ..........
|
||||
r2021 | rmudgett | 2010-10-14 13:35:48 -0500 (Thu, 14 Oct 2010) |
|
||||
10 lines Crash when receiving an unknown/unsupported message
|
||||
type. Fix double free of a call record and the subsequent
|
||||
continued use of the freed call record when receiving an
|
||||
unsupported/unknown message type. (closes issue #17968) Reported
|
||||
by: gelo Patches: issue_17968_v1.4.patch uploaded by rmudgett
|
||||
(license 664) issue_17968_v1.4.11.4.patch uploaded by rmudgett
|
||||
(license 664) ..........
|
||||
|
||||
* q931.c, pri_facility.c, pri.c, pri_internal.h: Merged revision
|
||||
2015 from https://origsvn.digium.com/svn/libpri/branches/1.4
|
||||
.......... r2015 | rmudgett | 2010-10-14 12:09:40 -0500 (Thu, 14
|
||||
Oct 2010) | 16 lines Segfault in pri_schedule_del() - ctrl value
|
||||
is invalid. Validate the given call pointer in libpri API calls.
|
||||
If the call pointer is not an active call record then a complaint
|
||||
message is issued and the API call aborts. The call pointer is
|
||||
likely stale. This patch is defensive. More information is needed
|
||||
to figure out why Asterisk still has a call pointer during its
|
||||
hangup sequence. (closes issue #17522) (closes issue #18032)
|
||||
Reported by: schmoozecom Patches: issue_18032_v1.4.patch uploaded
|
||||
by rmudgett (license 664) issue_18032_v1.4.11.4.patch uploaded by
|
||||
rmudgett (license 664) Tested by: rmudgett ..........
|
||||
|
||||
* pri_q931.h, q921.c, q931.c: Merged revision 1991 from
|
||||
https://origsvn.digium.com/svn/libpri/branches/1.4 ..........
|
||||
r1991 | rmudgett | 2010-09-13 16:21:37 -0500 (Mon, 13 Sep 2010) |
|
||||
9 lines PRI links do not retain active calls if the link comes
|
||||
back before T309 expires. The DL-ESTABLISH confirm event was not
|
||||
passed from Q.921 to Q.931 so Q.931 never cancelled the T309
|
||||
timer. Refactored q931_dl_tei_removal() and q931_dl_indication()
|
||||
into q931_dl_event() to allow the DL-ESTABLISH confirm/indication
|
||||
and DL-RELEASE confirm/indication events to be passed to Q.931.
|
||||
..........
|
||||
|
||||
* pri_q931.h, q921.c, q931.c, prisched.c, pri.c, pri_internal.h:
|
||||
Merged revision 1982 from
|
||||
https://origsvn.digium.com/svn/libpri/branches/1.4 ..........
|
||||
r1982 | rmudgett | 2010-09-13 11:07:24 -0500 (Mon, 13 Sep 2010) |
|
||||
18 lines BRI PTMP: Active channels not cleared when the interface
|
||||
goes down. If the connection to the terminal is lost while there
|
||||
are open channels on the interface, red alarm is reported, but
|
||||
the open channels are never cleared. Additionally, if you
|
||||
manually try to channel request hangup, Asterisk crashes. For
|
||||
PTMP, the T309 processing was not searching the call pool on the
|
||||
master control record. Additionally, for NT PTMP, the timeout
|
||||
events were not passed to the upper layer because the events were
|
||||
not put on the master control record where timer processing
|
||||
expects them. (closes issue #17865) Reported by: wimpy Patches:
|
||||
issue17865_v1.4.patch uploaded by rmudgett (license 664) Tested
|
||||
by: rmudgett, wimpy ..........
|
||||
|
||||
* q921.c, q931.c: Merged revision 1962 from
|
||||
https://origsvn.digium.com/svn/libpri/branches/1.4 ..........
|
||||
r1962 | rmudgett | 2010-09-07 19:13:24 -0500 (Tue, 07 Sep 2010) |
|
||||
21 lines Made Q.921 delay events to Q.931 if the event could
|
||||
immediately generate response frames. Q.921 was passing a
|
||||
q931_dl_indication(up) event to Q.931 before it was finished
|
||||
processing the frame. The q931_dl_indication(up) event could
|
||||
immediately send STATUS messages in the Q.921 intermediate state
|
||||
that would then get stuck in the tx queue with an invalid N(S).
|
||||
Q.921 was passing i-frames to Q.931 before it was finished
|
||||
processing the frame. The i-frames could cause Q.931 to
|
||||
immediately generate a response message that may cause the peer
|
||||
to see the P/F bit as incorrect. Delayed passing
|
||||
q931_dl_indication(up) events and i-frames to Q.931 until Q.921
|
||||
has completed processing the frame event. (The Q.921 SDL diagrams
|
||||
were designed with this assumption.) (closes issue #17360)
|
||||
Reported by: shawkris Patches: issue17360_v1.4.patch uploaded by
|
||||
rmudgett (license 664) Tested by: shawkris, rmudgett ..........
|
||||
|
||||
* q931.c: Merged revision 1961 from
|
||||
https://origsvn.digium.com/svn/libpri/branches/1.4 ..........
|
||||
r1961 | rmudgett | 2010-09-07 19:10:05 -0500 (Tue, 07 Sep 2010) |
|
||||
12 lines Prevent a CONNECT message from sending a CONNECT
|
||||
ACKNOWLEDGE in the wrong state. Filter the processing of the
|
||||
CONNECT message to prevent libpri from sending a CONNECT
|
||||
ACKNOWLEDGE when the call is in an inappropriate state. This can
|
||||
happen when we hang up an outgoing call after the other end has
|
||||
sent a CONNECT but before we have processed the CONNECT. (issue
|
||||
#17360) Reported by: shawkris Patches:
|
||||
issue17360_con_ack_v1.4.patch uploaded by rmudgett (license 664)
|
||||
..........
|
||||
|
||||
* q931.c, pri.c: Merged revision 1955,1958 from
|
||||
https://origsvn.digium.com/svn/libpri/branches/1.4 ..........
|
||||
r1955 | rmudgett | 2010-09-02 12:33:51 -0500 (Thu, 02 Sep 2010) |
|
||||
1 line Don't crash in __pri_new_tei() if a GR303 subchannel
|
||||
creation fails. .......... r1958 | rmudgett | 2010-09-07 18:13:04
|
||||
-0500 (Tue, 07 Sep 2010) | 1 line Balance curly braces in
|
||||
post_handle_q931_message(). ..........
|
||||
|
||||
2010-08-30 Leif Madsen <lmadsen@digium.com>
|
||||
|
||||
* libpri 1.4.11.4 released.
|
||||
|
||||
2010-08-30 22:34 +0000 [r1939-1949] Richard Mudgett <rmudgett@digium.com>
|
||||
|
||||
* q931.c, q921.c: Merged revisions 1923,1928-1929 via svnmerge from
|
||||
https://origsvn.digium.com/svn/libpri/branches/1.4 ........ r1923
|
||||
| rmudgett | 2010-08-30 14:31:46 -0500 (Mon, 30 Aug 2010) | 18
|
||||
lines 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. ........ r1928 | rmudgett |
|
||||
2010-08-30 15:30:59 -0500 (Mon, 30 Aug 2010) | 9 lines
|
||||
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.
|
||||
........ r1929 | rmudgett | 2010-08-30 15:49:11 -0500 (Mon, 30
|
||||
Aug 2010) | 2 lines Reduced fake MDL-ERROR (Z) message severity
|
||||
to be visible only when debugging enabled. ........
|
||||
|
||||
* q921.c: Merged revisions 1918 via svnmerge from
|
||||
https://origsvn.digium.com/svn/libpri/branches/1.4 ........ r1918
|
||||
| rmudgett | 2010-08-30 12:53:33 -0500 (Mon, 30 Aug 2010) | 41
|
||||
lines 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 ........
|
||||
|
||||
* rose.c, rosetest.c: Merged revisions 1904 via svnmerge from
|
||||
https://origsvn.digium.com/svn/libpri/branches/1.4 ........ r1904
|
||||
| rmudgett | 2010-08-27 10:54:17 -0500 (Fri, 27 Aug 2010) | 15
|
||||
lines 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
|
||||
........
|
||||
|
||||
* rosetest.c, pri.c, q921.c: Merged revisions 1878,1883-1884,1894
|
||||
via svnmerge from
|
||||
https://origsvn.digium.com/svn/libpri/branches/1.4 ........ r1878
|
||||
| mattf | 2010-08-23 17:13:44 -0500 (Mon, 23 Aug 2010) | 1 line
|
||||
Add silly fake MDL error Z for kicking L2 to reactivate if a DISC
|
||||
or DM is received in proper states on PTP links. ........ r1883 |
|
||||
rmudgett | 2010-08-25 11:38:29 -0500 (Wed, 25 Aug 2010) | 2 lines
|
||||
Don't silently fail to post our fake MDL-ERROR(Z). ........ r1884
|
||||
| rmudgett | 2010-08-25 12:17:09 -0500 (Wed, 25 Aug 2010) | 2
|
||||
lines Added gripe check to rosetest for invalid operation and
|
||||
error codes. ........ r1894 | rmudgett | 2010-08-26 18:26:16
|
||||
-0500 (Thu, 26 Aug 2010) | 1 line Make pri_dump_event() only
|
||||
print the event name. ........
|
||||
|
||||
* q931.c: Merged revisions 1853 via svnmerge from
|
||||
https://origsvn.digium.com/svn/libpri/branches/1.4 ........ r1853
|
||||
| rmudgett | 2010-08-06 13:35:35 -0500 (Fri, 06 Aug 2010) | 18
|
||||
lines 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 ........
|
||||
|
||||
* q931.c, q921.c: Merged revisions 1848,1852 via svnmerge from
|
||||
https://origsvn.digium.com/svn/libpri/branches/1.4 ........ r1848
|
||||
| rmudgett | 2010-08-03 18:04:52 -0500 (Tue, 03 Aug 2010) | 11
|
||||
lines 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. ........ r1852 |
|
||||
rmudgett | 2010-08-06 13:22:39 -0500 (Fri, 06 Aug 2010) | 1 line
|
||||
Learn (AGAIN!) why state 7 and state 8 transitions were
|
||||
suppressed. ........
|
||||
|
||||
* q921.c: Merged revisions 1845 via svnmerge from
|
||||
https://origsvn.digium.com/svn/libpri/branches/1.4 ........ r1845
|
||||
| rmudgett | 2010-08-03 12:33:54 -0500 (Tue, 03 Aug 2010) | 10
|
||||
lines 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) ........
|
||||
|
||||
* rosetest.c, q921.c: Merged revisions 1829-1830,1842 via svnmerge
|
||||
from https://origsvn.digium.com/svn/libpri/branches/1.4 ........
|
||||
r1829 | rmudgett | 2010-07-16 12:15:07 -0500 (Fri, 16 Jul 2010) |
|
||||
1 line Added a libpri version output line as a sanity check for
|
||||
rosetest. ........ r1830 | rmudgett | 2010-07-16 12:20:21 -0500
|
||||
(Fri, 16 Jul 2010) | 1 line Only need to output one version of
|
||||
the version message. ........ r1842 | rmudgett | 2010-08-02
|
||||
13:47:10 -0500 (Mon, 02 Aug 2010) | 5 lines 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.)
|
||||
........
|
||||
|
||||
* rosetest.c, rose_qsig_name.c: Merged revisions 1828 via svnmerge
|
||||
from https://origsvn.digium.com/svn/libpri/branches/1.4 ........
|
||||
r1828 | rmudgett | 2010-07-16 11:37:07 -0500 (Fri, 16 Jul 2010) |
|
||||
18 lines 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 Leif Madsen <lmadsen@digium.com>
|
||||
|
||||
* libpri 1.4.11.3 released.
|
||||
|
||||
185
pri.c
185
pri.c
@@ -324,7 +324,7 @@ struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master,
|
||||
p->subchannel = __pri_new_tei(-1, node, PRI_SWITCH_GR303_EOC_PATH, p, NULL, NULL, NULL, Q921_TEI_GR303_EOC_PATH, 0);
|
||||
if (!p->subchannel) {
|
||||
free(p);
|
||||
p = NULL;
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case PRI_SWITCH_GR303_TMC:
|
||||
@@ -334,7 +334,7 @@ struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master,
|
||||
p->subchannel = __pri_new_tei(-1, node, PRI_SWITCH_GR303_TMC_SWITCHING, p, NULL, NULL, NULL, Q921_TEI_GR303_TMC_SWITCHING, 0);
|
||||
if (!p->subchannel) {
|
||||
free(p);
|
||||
p = NULL;
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case PRI_SWITCH_GR303_TMC_SWITCHING:
|
||||
@@ -365,8 +365,15 @@ struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master,
|
||||
|
||||
void pri_call_set_useruser(q931_call *c, const char *userchars)
|
||||
{
|
||||
if (userchars)
|
||||
libpri_copy_string(c->useruserinfo, userchars, sizeof(c->useruserinfo));
|
||||
/*
|
||||
* There is a slight risk here if c is actually stale. However,
|
||||
* if it is stale then it is better to catch it here than to
|
||||
* write with it.
|
||||
*/
|
||||
if (!userchars || !pri_is_call_valid(NULL, c)) {
|
||||
return;
|
||||
}
|
||||
libpri_copy_string(c->useruserinfo, userchars, sizeof(c->useruserinfo));
|
||||
}
|
||||
|
||||
void pri_sr_set_useruser(struct pri_sr *sr, const char *userchars)
|
||||
@@ -434,32 +441,32 @@ 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" },
|
||||
/* *INDENT-ON* */
|
||||
};
|
||||
|
||||
@@ -575,74 +582,83 @@ void pri_facility_enable(struct pri *pri)
|
||||
|
||||
int pri_acknowledge(struct pri *pri, q931_call *call, int channel, int info)
|
||||
{
|
||||
if (!pri || !call)
|
||||
if (!pri || !pri_is_call_valid(pri, call)) {
|
||||
return -1;
|
||||
}
|
||||
return q931_alerting(pri, call, channel, info);
|
||||
}
|
||||
|
||||
int pri_proceeding(struct pri *pri, q931_call *call, int channel, int info)
|
||||
{
|
||||
if (!pri || !call)
|
||||
if (!pri || !pri_is_call_valid(pri, call)) {
|
||||
return -1;
|
||||
}
|
||||
return q931_call_proceeding(pri, call, channel, info);
|
||||
}
|
||||
|
||||
int pri_progress_with_cause(struct pri *pri, q931_call *call, int channel, int info, int cause)
|
||||
{
|
||||
if (!pri || !call)
|
||||
if (!pri || !pri_is_call_valid(pri, call)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return q931_call_progress_with_cause(pri, call, channel, info, cause);
|
||||
}
|
||||
|
||||
int pri_progress(struct pri *pri, q931_call *call, int channel, int info)
|
||||
{
|
||||
if (!pri || !call)
|
||||
if (!pri || !pri_is_call_valid(pri, call)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return q931_call_progress(pri, call, channel, info);
|
||||
}
|
||||
|
||||
int pri_information(struct pri *pri, q931_call *call, char digit)
|
||||
{
|
||||
if (!pri || !call)
|
||||
if (!pri || !pri_is_call_valid(pri, call)) {
|
||||
return -1;
|
||||
}
|
||||
return q931_information(pri, call, digit);
|
||||
}
|
||||
|
||||
int pri_keypad_facility(struct pri *pri, q931_call *call, const char *digits)
|
||||
{
|
||||
if (!pri || !call || !digits || !digits[0])
|
||||
if (!pri || !pri_is_call_valid(pri, call) || !digits || !digits[0]) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return q931_keypad_facility(pri, call, digits);
|
||||
}
|
||||
|
||||
int pri_notify(struct pri *pri, q931_call *call, int channel, int info)
|
||||
{
|
||||
if (!pri || !call)
|
||||
if (!pri || !pri_is_call_valid(pri, call)) {
|
||||
return -1;
|
||||
}
|
||||
return q931_notify(pri, call, channel, info);
|
||||
}
|
||||
|
||||
void pri_destroycall(struct pri *pri, q931_call *call)
|
||||
{
|
||||
if (pri && call)
|
||||
if (pri && pri_is_call_valid(pri, call)) {
|
||||
q931_destroycall(pri, call);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int pri_need_more_info(struct pri *pri, q931_call *call, int channel, int nonisdn)
|
||||
{
|
||||
if (!pri || !call)
|
||||
if (!pri || !pri_is_call_valid(pri, call)) {
|
||||
return -1;
|
||||
}
|
||||
return q931_setup_ack(pri, call, channel, nonisdn);
|
||||
}
|
||||
|
||||
int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn)
|
||||
{
|
||||
if (!pri || !call)
|
||||
if (!pri || !pri_is_call_valid(pri, call)) {
|
||||
return -1;
|
||||
}
|
||||
return q931_connect(pri, call, channel, nonisdn);
|
||||
}
|
||||
|
||||
@@ -738,7 +754,7 @@ int pri_connected_line_update(struct pri *ctrl, q931_call *call, const struct pr
|
||||
unsigned idx;
|
||||
struct q931_call *subcall;
|
||||
|
||||
if (!ctrl || !call) {
|
||||
if (!ctrl || !pri_is_call_valid(ctrl, call)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -804,7 +820,7 @@ int pri_redirecting_update(struct pri *ctrl, q931_call *call, const struct pri_p
|
||||
unsigned idx;
|
||||
struct q931_call *subcall;
|
||||
|
||||
if (!ctrl || !call) {
|
||||
if (!ctrl || !pri_is_call_valid(ctrl, call)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -908,23 +924,31 @@ int pri_redirecting_update(struct pri *ctrl, q931_call *call, const struct pri_p
|
||||
/* deprecated routines, use pri_hangup */
|
||||
int pri_release(struct pri *pri, q931_call *call, int cause)
|
||||
{
|
||||
if (!pri || !call)
|
||||
if (!pri || !pri_is_call_valid(pri, call)) {
|
||||
return -1;
|
||||
}
|
||||
return q931_release(pri, call, cause);
|
||||
}
|
||||
|
||||
int pri_disconnect(struct pri *pri, q931_call *call, int cause)
|
||||
{
|
||||
if (!pri || !call)
|
||||
if (!pri || !pri_is_call_valid(pri, call)) {
|
||||
return -1;
|
||||
}
|
||||
return q931_disconnect(pri, call, cause);
|
||||
}
|
||||
#endif
|
||||
|
||||
int pri_channel_bridge(q931_call *call1, q931_call *call2)
|
||||
{
|
||||
if (!call1 || !call2)
|
||||
/*
|
||||
* There is a slight risk here if call1 or call2 is actually
|
||||
* stale. However, if they are stale then it is better to catch
|
||||
* it here than to write with these pointers.
|
||||
*/
|
||||
if (!pri_is_call_valid(NULL, call1) || !pri_is_call_valid(NULL, call2)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Make sure we have compatible switchtypes */
|
||||
if (call1->pri->switchtype != call2->pri->switchtype)
|
||||
@@ -976,8 +1000,9 @@ void pri_hangup_fix_enable(struct pri *ctrl, int enable)
|
||||
|
||||
int pri_hangup(struct pri *pri, q931_call *call, int cause)
|
||||
{
|
||||
if (!pri || !call)
|
||||
if (!pri || !pri_is_call_valid(pri, call)) {
|
||||
return -1;
|
||||
}
|
||||
if (cause == -1)
|
||||
/* normal clear cause */
|
||||
cause = PRI_CAUSE_NORMAL_CLEARING;
|
||||
@@ -1019,26 +1044,6 @@ 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)
|
||||
@@ -1075,8 +1080,10 @@ int pri_mwi_activate(struct pri *pri, q931_call *c, char *caller, int callerplan
|
||||
int calledplan)
|
||||
{
|
||||
struct pri_sr req;
|
||||
if (!pri || !c)
|
||||
|
||||
if (!pri || !pri_is_call_valid(pri, c)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pri_sr_init(&req);
|
||||
pri_sr_set_connection_call_independent(&req);
|
||||
@@ -1095,8 +1102,10 @@ int pri_mwi_deactivate(struct pri *pri, q931_call *c, char *caller, int callerpl
|
||||
int calledplan)
|
||||
{
|
||||
struct pri_sr req;
|
||||
if (!pri || !c)
|
||||
|
||||
if (!pri || !pri_is_call_valid(pri, c)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pri_sr_init(&req);
|
||||
pri_sr_set_connection_call_independent(&req);
|
||||
@@ -1113,8 +1122,9 @@ int pri_mwi_deactivate(struct pri *pri, q931_call *c, char *caller, int callerpl
|
||||
|
||||
int pri_setup(struct pri *pri, q931_call *c, struct pri_sr *req)
|
||||
{
|
||||
if (!pri || !c)
|
||||
if (!pri || !pri_is_call_valid(pri, c)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return q931_setup(pri, c, req);
|
||||
}
|
||||
@@ -1124,8 +1134,11 @@ int pri_call(struct pri *pri, q931_call *c, int transmode, int channel, int excl
|
||||
int calledplan, int ulayer1)
|
||||
{
|
||||
struct pri_sr req;
|
||||
if (!pri || !c)
|
||||
|
||||
if (!pri || !pri_is_call_valid(pri, c)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pri_sr_init(&req);
|
||||
pri_sr_set_caller(&req, caller, callername, callerplan, callerpres);
|
||||
pri_sr_set_called(&req, called, calledplan, 0);
|
||||
@@ -1348,7 +1361,7 @@ char *pri_dump_info_str(struct pri *ctrl)
|
||||
enum PRI_TIMERS_AND_COUNTERS tmr;
|
||||
|
||||
tmr = pri_timer[idx].number;
|
||||
if (0 <= ctrl->timers[tmr] || tmr == PRI_TIMER_T309) {
|
||||
if (0 <= ctrl->timers[tmr]) {
|
||||
used = pri_snprintf(buf, used, buf_size, " %s: %d\n",
|
||||
pri_timer[idx].name, ctrl->timers[tmr]);
|
||||
}
|
||||
@@ -1364,18 +1377,27 @@ char *pri_dump_info_str(struct pri *ctrl)
|
||||
|
||||
int pri_get_crv(struct pri *pri, q931_call *call, int *callmode)
|
||||
{
|
||||
if (!pri || !pri_is_call_valid(pri, call)) {
|
||||
return -1;
|
||||
}
|
||||
return q931_call_getcrv(pri, call, callmode);
|
||||
}
|
||||
|
||||
int pri_set_crv(struct pri *pri, q931_call *call, int crv, int callmode)
|
||||
{
|
||||
if (!pri || !pri_is_call_valid(pri, call)) {
|
||||
return -1;
|
||||
}
|
||||
return q931_call_setcrv(pri, call, crv, callmode);
|
||||
}
|
||||
|
||||
void pri_enslave(struct pri *master, struct pri *slave)
|
||||
{
|
||||
if (master && slave)
|
||||
if (master && slave) {
|
||||
slave->callpool = &master->localpool;
|
||||
slave->nfas = 1;
|
||||
master->nfas = 1;
|
||||
}
|
||||
}
|
||||
|
||||
struct pri_sr *pri_sr_new(void)
|
||||
@@ -1514,7 +1536,7 @@ void pri_hold_enable(struct pri *ctrl, int enable)
|
||||
|
||||
int pri_hold(struct pri *ctrl, q931_call *call)
|
||||
{
|
||||
if (!ctrl || !call) {
|
||||
if (!ctrl || !pri_is_call_valid(ctrl, call)) {
|
||||
return -1;
|
||||
}
|
||||
return q931_send_hold(ctrl, call);
|
||||
@@ -1522,7 +1544,7 @@ int pri_hold(struct pri *ctrl, q931_call *call)
|
||||
|
||||
int pri_hold_ack(struct pri *ctrl, q931_call *call)
|
||||
{
|
||||
if (!ctrl || !call) {
|
||||
if (!ctrl || !pri_is_call_valid(ctrl, call)) {
|
||||
return -1;
|
||||
}
|
||||
return q931_send_hold_ack(ctrl, call);
|
||||
@@ -1530,7 +1552,7 @@ int pri_hold_ack(struct pri *ctrl, q931_call *call)
|
||||
|
||||
int pri_hold_rej(struct pri *ctrl, q931_call *call, int cause)
|
||||
{
|
||||
if (!ctrl || !call) {
|
||||
if (!ctrl || !pri_is_call_valid(ctrl, call)) {
|
||||
return -1;
|
||||
}
|
||||
return q931_send_hold_rej(ctrl, call, cause);
|
||||
@@ -1538,7 +1560,7 @@ int pri_hold_rej(struct pri *ctrl, q931_call *call, int cause)
|
||||
|
||||
int pri_retrieve(struct pri *ctrl, q931_call *call, int channel)
|
||||
{
|
||||
if (!ctrl || !call) {
|
||||
if (!ctrl || !pri_is_call_valid(ctrl, call)) {
|
||||
return -1;
|
||||
}
|
||||
return q931_send_retrieve(ctrl, call, channel);
|
||||
@@ -1546,7 +1568,7 @@ int pri_retrieve(struct pri *ctrl, q931_call *call, int channel)
|
||||
|
||||
int pri_retrieve_ack(struct pri *ctrl, q931_call *call, int channel)
|
||||
{
|
||||
if (!ctrl || !call) {
|
||||
if (!ctrl || !pri_is_call_valid(ctrl, call)) {
|
||||
return -1;
|
||||
}
|
||||
return q931_send_retrieve_ack(ctrl, call, channel);
|
||||
@@ -1554,7 +1576,7 @@ 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 (!ctrl || !call) {
|
||||
if (!ctrl || !pri_is_call_valid(ctrl, call)) {
|
||||
return -1;
|
||||
}
|
||||
return q931_send_retrieve_rej(ctrl, call, cause);
|
||||
@@ -1562,8 +1584,9 @@ int pri_retrieve_rej(struct pri *ctrl, q931_call *call, int cause)
|
||||
|
||||
int pri_callrerouting_facility(struct pri *pri, q931_call *call, const char *dest, const char* original, const char* reason)
|
||||
{
|
||||
if (!pri || !call || !dest)
|
||||
if (!pri || !pri_is_call_valid(pri, call) || !dest) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return qsig_cf_callrerouting(pri, call, dest, original, reason);
|
||||
}
|
||||
@@ -1582,7 +1605,7 @@ int pri_reroute_call(struct pri *ctrl, q931_call *call, const struct pri_party_i
|
||||
struct q931_party_id local_caller;
|
||||
struct q931_party_redirecting reroute;
|
||||
|
||||
if (!ctrl || !call || !deflection) {
|
||||
if (!ctrl || !pri_is_call_valid(ctrl, call) || !deflection) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -3180,7 +3180,7 @@ int pri_rerouting_rsp(struct pri *ctrl, q931_call *call, int invoke_id, enum PRI
|
||||
{
|
||||
enum rose_error_code rose_err;
|
||||
|
||||
if (!ctrl || !call) {
|
||||
if (!ctrl || !pri_is_call_valid(ctrl, call)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -84,6 +84,7 @@ struct pri {
|
||||
int sapi;
|
||||
int tei;
|
||||
int protodisc;
|
||||
unsigned int nfas:1;/* TRUE if this D channel is involved with an NFAS group */
|
||||
unsigned int bri:1;
|
||||
unsigned int acceptinbanddisconnect:1; /* Should we allow inband progress after DISCONNECT? */
|
||||
unsigned int sendfacility:1;
|
||||
@@ -542,11 +543,26 @@ struct d_ctrl_dummy {
|
||||
struct q931_call dummy_call;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Check if the given call ptr is valid.
|
||||
*
|
||||
* \param ctrl D channel controller.
|
||||
* \param call Q.931 call leg.
|
||||
*
|
||||
* \retval TRUE if call ptr is valid.
|
||||
* \retval FALSE if call ptr is invalid.
|
||||
*/
|
||||
#define pri_is_call_valid(ctrl, call) \
|
||||
q931_is_call_valid(ctrl, call, __PRETTY_FUNCTION__, __LINE__)
|
||||
|
||||
int q931_is_call_valid(struct pri *ctrl, struct q931_call *call, const char *func_name, unsigned long func_line);
|
||||
|
||||
extern int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data);
|
||||
|
||||
extern pri_event *pri_schedule_run(struct pri *pri);
|
||||
|
||||
extern void pri_schedule_del(struct pri *pri, int ev);
|
||||
int pri_schedule_check(struct pri *ctrl, int id, void (*function)(void *data), void *data);
|
||||
|
||||
extern pri_event *pri_mkerror(struct pri *pri, char *errstr);
|
||||
|
||||
|
||||
10
pri_q931.h
10
pri_q931.h
@@ -494,7 +494,15 @@ void q931_dump(struct pri *ctrl, int tei, q931_h *h, int len, int txrx);
|
||||
|
||||
void q931_destroycall(struct pri *pri, q931_call *c);
|
||||
|
||||
extern void q931_dl_indication(struct pri *pri, int event);
|
||||
enum Q931_DL_EVENT {
|
||||
Q931_DL_EVENT_NONE,
|
||||
Q931_DL_EVENT_DL_ESTABLISH_IND,
|
||||
Q931_DL_EVENT_DL_ESTABLISH_CONFIRM,
|
||||
Q931_DL_EVENT_DL_RELEASE_IND,
|
||||
Q931_DL_EVENT_DL_RELEASE_CONFIRM,
|
||||
Q931_DL_EVENT_TEI_REMOVAL,
|
||||
};
|
||||
void q931_dl_event(struct pri *link, enum Q931_DL_EVENT event);
|
||||
|
||||
int q931_send_hold(struct pri *ctrl, struct q931_call *call);
|
||||
int q931_send_hold_ack(struct pri *ctrl, struct q931_call *call);
|
||||
|
||||
28
prisched.c
28
prisched.c
@@ -184,3 +184,31 @@ void pri_schedule_del(struct pri *ctrl, int id)
|
||||
pri_error(ctrl, "Asked to delete sched id %d???\n", id);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Is the scheduled event this callback.
|
||||
*
|
||||
* \param ctrl D channel controller.
|
||||
* \param id Scheduled event id to check.
|
||||
* 0 is a disabled/unscheduled event id.
|
||||
* 1 - MAX_SCHED is a valid event id.
|
||||
* \param function Callback function to call when timeout.
|
||||
* \param data Value to give callback function when timeout.
|
||||
*
|
||||
* \return TRUE if scheduled event has the callback.
|
||||
*/
|
||||
int pri_schedule_check(struct pri *ctrl, int id, void (*function)(void *data), void *data)
|
||||
{
|
||||
/* Scheduling runs on master channels only */
|
||||
ctrl = PRI_MASTER(ctrl);
|
||||
|
||||
if (0 < id && id <= MAX_SCHED) {
|
||||
if (ctrl->pri_sched[id - 1].callback == function
|
||||
&& ctrl->pri_sched[id - 1].data == data) {
|
||||
return 1;
|
||||
}
|
||||
} else if (id) {
|
||||
pri_error(ctrl, "Asked to check sched id %d???\n", id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
680
q931.c
680
q931.c
@@ -320,6 +320,76 @@ static int q931_encode_channel(const q931_call *call)
|
||||
| held_call;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Check if the given call ptr is valid.
|
||||
*
|
||||
* \param ctrl D channel controller.
|
||||
* \param call Q.931 call leg.
|
||||
* \param func_name Calling function name for debug tracing. (__PRETTY_FUNCTION__)
|
||||
* \param func_line Calling function line number for debug tracing. (__LINE__)
|
||||
*
|
||||
* \retval TRUE if call ptr is valid.
|
||||
* \retval FALSE if call ptr is invalid.
|
||||
*/
|
||||
int q931_is_call_valid(struct pri *ctrl, struct q931_call *call, const char *func_name, unsigned long func_line)
|
||||
{
|
||||
struct q931_call *cur;
|
||||
struct pri *gripe;
|
||||
struct pri *link;
|
||||
int idx;
|
||||
|
||||
if (!call) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ctrl) {
|
||||
/* Must use suspect ctrl from call ptr. */
|
||||
if (!call->pri) {
|
||||
pri_message(NULL,
|
||||
"!! %s() line:%lu Called with invalid call ptr (%p) (No ctrl)\n",
|
||||
func_name, func_line, call);
|
||||
return 0;
|
||||
}
|
||||
/* Find the master - He has the call pool */
|
||||
ctrl = PRI_MASTER(call->pri);
|
||||
gripe = NULL;
|
||||
} else {
|
||||
/* Find the master - He has the call pool */
|
||||
ctrl = PRI_MASTER(ctrl);
|
||||
gripe = ctrl;
|
||||
}
|
||||
|
||||
/* Check real call records. */
|
||||
for (cur = *ctrl->callpool; cur; cur = cur->next) {
|
||||
if (call == cur) {
|
||||
/* Found it. */
|
||||
return 1;
|
||||
}
|
||||
if (cur->outboundbroadcast) {
|
||||
/* Check subcalls for call ptr. */
|
||||
for (idx = 0; idx < ARRAY_LEN(cur->subcalls); ++idx) {
|
||||
if (call == cur->subcalls[idx]) {
|
||||
/* Found it. */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check dummy call records. */
|
||||
for (link = ctrl; link; link = link->subchannel) {
|
||||
if (link->dummy_call == call) {
|
||||
/* Found it. */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Well it looks like this is a stale call ptr. */
|
||||
pri_message(gripe, "!! %s() line:%lu Called with invalid call ptr (%p)\n",
|
||||
func_name, func_line, call);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Initialize the given struct q931_party_name
|
||||
*
|
||||
@@ -885,7 +955,12 @@ static int receive_channel_id(int full_ie, struct pri *ctrl, q931_call *call, in
|
||||
return -1;
|
||||
}
|
||||
if (ie->data[pos] & 0x10) {
|
||||
/* Expect Slot Map */
|
||||
/*
|
||||
* Expect Slot Map
|
||||
* Note that we are assuming only T1's use slot maps which is wrong
|
||||
* but oh well... We would need to know what type of line we are
|
||||
* connected with (T1 or E1) to interpret the map correctly anyway.
|
||||
*/
|
||||
call->slotmap = 0;
|
||||
pos++;
|
||||
for (x=0;x<3;x++) {
|
||||
@@ -963,22 +1038,26 @@ static int transmit_channel_id(int full_ie, struct pri *ctrl, q931_call *call, i
|
||||
&& !(call->chanflags & FLAG_WHOLE_INTERFACE)) {
|
||||
/* The 3.2 and 3.3 octets need to be present */
|
||||
ie->data[pos] = 0x83;
|
||||
if (call->slotmap != -1) {
|
||||
int octet;
|
||||
|
||||
/* We have to send a channel map */
|
||||
ie->data[pos++] |= 0x10;
|
||||
for (octet = 3; octet--;) {
|
||||
ie->data[pos++] = (call->slotmap >> (8 * octet)) & 0xff;
|
||||
}
|
||||
} else {
|
||||
/* Channel number specified */
|
||||
if (0 < call->channelno && call->channelno != 0xff) {
|
||||
/* Channel number specified and preferred over slot map if we have one. */
|
||||
++pos;
|
||||
if (ctrl->chan_mapping_logical && call->channelno > 16) {
|
||||
ie->data[pos++] = 0x80 | (call->channelno - 1);
|
||||
} else {
|
||||
ie->data[pos++] = 0x80 | call->channelno;
|
||||
}
|
||||
} else if (call->slotmap != -1) {
|
||||
int octet;
|
||||
|
||||
/* We have to send a slot map */
|
||||
ie->data[pos++] |= 0x10;
|
||||
for (octet = 3; octet--;) {
|
||||
ie->data[pos++] = (call->slotmap >> (8 * octet)) & 0xff;
|
||||
}
|
||||
} else {
|
||||
pri_error(ctrl, "XXX We need either a channelno or slotmap but have neither!\n");
|
||||
/* Discard this malformed ie. */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3915,6 +3994,85 @@ static char *disc2str(int disc)
|
||||
return code2str(disc, discs, sizeof(discs) / sizeof(discs[0]));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Dump the Q.931 message header.
|
||||
*
|
||||
* \param ctrl D channel controller.
|
||||
* \param tei TEI the packet is associated with.
|
||||
* \param h Q.931 packet contents/header.
|
||||
* \param len Received length of the Q.931 packet.
|
||||
* \param c Message direction prefix character.
|
||||
*
|
||||
* \retval 0 on success.
|
||||
* \retval -1 on error.
|
||||
*/
|
||||
static int q931_dump_header(struct pri *ctrl, int tei, q931_h *h, int len, char c)
|
||||
{
|
||||
q931_mh *mh;
|
||||
int cref;
|
||||
|
||||
pri_message(ctrl, "%c Protocol Discriminator: %s (%d) len=%d\n", c, disc2str(h->pd), h->pd, len);
|
||||
|
||||
if (len < 2 || len < 2 + h->crlen) {
|
||||
pri_message(ctrl, "%c Message too short for call reference. len=%d\n",
|
||||
c, len);
|
||||
return -1;
|
||||
}
|
||||
cref = q931_cr(h);
|
||||
pri_message(ctrl, "%c TEI=%d Call Ref: len=%2d (reference %d/0x%X) (%s)\n",
|
||||
c, tei, h->crlen, cref & ~Q931_CALL_REFERENCE_FLAG,
|
||||
cref & ~Q931_CALL_REFERENCE_FLAG, (cref == Q931_DUMMY_CALL_REFERENCE)
|
||||
? "Dummy"
|
||||
: (cref & Q931_CALL_REFERENCE_FLAG)
|
||||
? "Sent to originator" : "Sent from originator");
|
||||
|
||||
if (len < 3 + h->crlen) {
|
||||
pri_message(ctrl, "%c Message too short for supported protocols. len=%d\n",
|
||||
c, len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Message header begins at the end of the call reference number */
|
||||
mh = (q931_mh *)(h->contents + h->crlen);
|
||||
switch (h->pd) {
|
||||
case MAINTENANCE_PROTOCOL_DISCRIMINATOR_1:
|
||||
case MAINTENANCE_PROTOCOL_DISCRIMINATOR_2:
|
||||
pri_message(ctrl, "%c Message Type: %s (%d)\n", c, maintenance_msg2str(mh->msg, h->pd), mh->msg);
|
||||
break;
|
||||
default:
|
||||
/* Unknown protocol discriminator but we will treat it as Q.931 anyway. */
|
||||
case GR303_PROTOCOL_DISCRIMINATOR:
|
||||
case Q931_PROTOCOL_DISCRIMINATOR:
|
||||
pri_message(ctrl, "%c Message Type: %s (%d)\n", c, msg2str(mh->msg), mh->msg);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Q.931 is passing this message to Q.921 debug indication.
|
||||
*
|
||||
* \param ctrl D channel controller.
|
||||
* \param tei TEI the packet is associated with.
|
||||
* \param h Q.931 packet contents/header.
|
||||
* \param len Received length of the Q.931 packet
|
||||
*
|
||||
* \return Nothing
|
||||
*/
|
||||
static void q931_to_q921_passing_dump(struct pri *ctrl, int tei, q931_h *h, int len)
|
||||
{
|
||||
char c;
|
||||
|
||||
c = '>';
|
||||
|
||||
pri_message(ctrl, "\n");
|
||||
pri_message(ctrl, "%c DL-DATA request\n", c);
|
||||
q931_dump_header(ctrl, tei, h, len, c);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Debug dump the given Q.931 packet.
|
||||
*
|
||||
@@ -3934,46 +4092,19 @@ void q931_dump(struct pri *ctrl, int tei, q931_h *h, int len, int txrx)
|
||||
int r;
|
||||
int cur_codeset;
|
||||
int codeset;
|
||||
int cref;
|
||||
|
||||
c = txrx ? '>' : '<';
|
||||
|
||||
pri_message(ctrl, "%c Protocol Discriminator: %s (%d) len=%d\n", c, disc2str(h->pd), h->pd, len);
|
||||
|
||||
if (len < 2 || len < 2 + h->crlen) {
|
||||
pri_message(ctrl, "%c Message too short for call reference. len=%d\n",
|
||||
c, len);
|
||||
return;
|
||||
if (!(ctrl->debug & (PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW))) {
|
||||
/* Put out a blank line if Q.921 is not dumping. */
|
||||
pri_message(ctrl, "\n");
|
||||
}
|
||||
cref = q931_cr(h);
|
||||
pri_message(ctrl, "%c TEI=%d Call Ref: len=%2d (reference %d/0x%X) (%s)\n",
|
||||
c, tei, h->crlen, cref & ~Q931_CALL_REFERENCE_FLAG,
|
||||
cref & ~Q931_CALL_REFERENCE_FLAG, (cref == Q931_DUMMY_CALL_REFERENCE)
|
||||
? "Dummy"
|
||||
: (cref & Q931_CALL_REFERENCE_FLAG)
|
||||
? "Sent to originator" : "Sent from originator");
|
||||
|
||||
if (len < 3 + h->crlen) {
|
||||
pri_message(ctrl, "%c Message too short for supported protocols. len=%d\n",
|
||||
c, len);
|
||||
if (q931_dump_header(ctrl, tei, h, len, c)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Message header begins at the end of the call reference number */
|
||||
mh = (q931_mh *)(h->contents + h->crlen);
|
||||
switch (h->pd) {
|
||||
case MAINTENANCE_PROTOCOL_DISCRIMINATOR_1:
|
||||
case MAINTENANCE_PROTOCOL_DISCRIMINATOR_2:
|
||||
pri_message(ctrl, "%c Message Type: %s (%d)\n", c, maintenance_msg2str(mh->msg, h->pd), mh->msg);
|
||||
break;
|
||||
default:
|
||||
/* Unknown protocol discriminator but we will treat it as Q.931 anyway. */
|
||||
case GR303_PROTOCOL_DISCRIMINATOR:
|
||||
case Q931_PROTOCOL_DISCRIMINATOR:
|
||||
pri_message(ctrl, "%c Message Type: %s (%d)\n", c, msg2str(mh->msg), mh->msg);
|
||||
break;
|
||||
}
|
||||
/* Drop length of header, including call reference */
|
||||
mh = (q931_mh *)(h->contents + h->crlen);
|
||||
len -= (h->crlen + 3);
|
||||
codeset = cur_codeset = 0;
|
||||
for (x = 0; x < len; x += r) {
|
||||
@@ -4067,19 +4198,32 @@ static void init_header(struct pri *ctrl, q931_call *call, unsigned char *buf, q
|
||||
|
||||
static int q931_xmit(struct pri *ctrl, int tei, q931_h *h, int len, int cr, int uiframe)
|
||||
{
|
||||
if (uiframe) {
|
||||
q921_transmit_uiframe(ctrl, h, len);
|
||||
} else {
|
||||
q921_transmit_iframe(ctrl, tei, h, len, cr);
|
||||
}
|
||||
/* The transmit operation might dump the q921 header, so logging the q931
|
||||
message body after the transmit puts the sections of the message in the
|
||||
right order in the log */
|
||||
if (ctrl->debug & PRI_DEBUG_Q931_DUMP)
|
||||
q931_dump(ctrl, tei, h, len, 1);
|
||||
#ifdef LIBPRI_COUNTERS
|
||||
ctrl->q931_txcount++;
|
||||
#endif
|
||||
if (uiframe) {
|
||||
q921_transmit_uiframe(ctrl, h, len);
|
||||
if (ctrl->debug & PRI_DEBUG_Q931_DUMP) {
|
||||
/*
|
||||
* The transmit operation might dump the Q.921 header, so logging
|
||||
* the Q.931 message body after the transmit puts the sections of
|
||||
* the message in the right order in the log,
|
||||
*/
|
||||
q931_dump(ctrl, tei, h, len, 1);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Indicate passing the Q.931 message to Q.921 first. Q.921 may
|
||||
* have to request a TEI or bring the connection up before it can
|
||||
* actually send the message. Therefore, the Q.931 message may
|
||||
* actually get sent a few seconds later. Q.921 will dump the
|
||||
* Q.931 message as appropriate at that time.
|
||||
*/
|
||||
if (ctrl->debug & PRI_DEBUG_Q931_DUMP) {
|
||||
q931_to_q921_passing_dump(ctrl, tei, h, len);
|
||||
}
|
||||
q921_transmit_iframe(ctrl, tei, h, len, cr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -4109,6 +4253,7 @@ static int send_message(struct pri *ctrl, q931_call *call, int msgtype, int ies[
|
||||
int x;
|
||||
int codeset;
|
||||
int uiframe;
|
||||
int tei;
|
||||
|
||||
if (call->outboundbroadcast && call->master_call == call && msgtype != Q931_SETUP) {
|
||||
pri_error(ctrl,
|
||||
@@ -4137,6 +4282,7 @@ static int send_message(struct pri *ctrl, q931_call *call, int msgtype, int ies[
|
||||
/* Invert the logic */
|
||||
len = sizeof(buf) - len;
|
||||
|
||||
tei = call->pri->tei;
|
||||
uiframe = 0;
|
||||
if (BRI_NT_PTMP(ctrl)) {
|
||||
/* NT PTMP is the only mode that can broadcast Q.931 messages. */
|
||||
@@ -4153,7 +4299,7 @@ static int send_message(struct pri *ctrl, q931_call *call, int msgtype, int ies[
|
||||
uiframe = 1;
|
||||
break;
|
||||
case Q931_FACILITY:
|
||||
if (call->pri->tei == Q921_TEI_GROUP) {
|
||||
if (tei == Q921_TEI_GROUP) {
|
||||
/* Broadcast TEI. */
|
||||
if (q931_is_dummy_call(call)) {
|
||||
/*
|
||||
@@ -4178,8 +4324,14 @@ static int send_message(struct pri *ctrl, q931_call *call, int msgtype, int ies[
|
||||
"Sending message for call %p on call->pri: %p with TEI/SAPI %d/%d\n",
|
||||
call, call->pri, call->pri->tei, call->pri->sapi);
|
||||
}
|
||||
} else if (call->pri->subchannel && BRI_TE_PTMP(ctrl)) {
|
||||
/*
|
||||
* Get the best available TEI value for the debug dump display.
|
||||
* We may not actually have a TEI assigned at the moment.
|
||||
*/
|
||||
tei = call->pri->subchannel->tei;
|
||||
}
|
||||
q931_xmit(call->pri, call->pri->tei, h, len, 1, uiframe);
|
||||
q931_xmit(call->pri, tei, h, len, 1, uiframe);
|
||||
call->acked = 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -4513,10 +4665,11 @@ static void pri_connect_timeout(void *data)
|
||||
{
|
||||
struct q931_call *c = data;
|
||||
struct pri *ctrl = c->pri;
|
||||
|
||||
if (ctrl->debug & PRI_DEBUG_Q931_STATE)
|
||||
pri_message(ctrl, "Timed out looking for connect acknowledge\n");
|
||||
c->retranstimer = 0;
|
||||
q931_disconnect(ctrl, c, PRI_CAUSE_NORMAL_CLEARING);
|
||||
|
||||
}
|
||||
|
||||
/* T308 expiry, first time */
|
||||
@@ -4524,9 +4677,11 @@ static void pri_release_timeout(void *data)
|
||||
{
|
||||
struct q931_call *c = data;
|
||||
struct pri *ctrl = c->pri;
|
||||
|
||||
if (ctrl->debug & PRI_DEBUG_Q931_STATE)
|
||||
pri_message(ctrl, "Timed out looking for release complete\n");
|
||||
c->t308_timedout++;
|
||||
c->retranstimer = 0;
|
||||
c->alive = 1;
|
||||
|
||||
/* The call to q931_release will re-schedule T308 */
|
||||
@@ -4538,6 +4693,8 @@ static void pri_release_finaltimeout(void *data)
|
||||
{
|
||||
struct q931_call *c = data;
|
||||
struct pri *ctrl = c->pri;
|
||||
|
||||
c->retranstimer = 0;
|
||||
c->alive = 1;
|
||||
if (ctrl->debug & PRI_DEBUG_Q931_STATE)
|
||||
pri_message(ctrl, "Final time-out looking for release complete\n");
|
||||
@@ -4564,8 +4721,10 @@ static void pri_disconnect_timeout(void *data)
|
||||
{
|
||||
struct q931_call *c = data;
|
||||
struct pri *ctrl = c->pri;
|
||||
|
||||
if (ctrl->debug & PRI_DEBUG_Q931_STATE)
|
||||
pri_message(ctrl, "Timed out looking for release\n");
|
||||
c->retranstimer = 0;
|
||||
c->alive = 1;
|
||||
q931_release(ctrl, c, PRI_CAUSE_NORMAL_CLEARING);
|
||||
}
|
||||
@@ -4864,6 +5023,9 @@ int q931_setup(struct pri *ctrl, q931_call *c, struct pri_sr *req)
|
||||
|
||||
pri_call_add_standard_apdus(ctrl, c);
|
||||
|
||||
if (BRI_NT_PTMP(ctrl)) {
|
||||
c->outboundbroadcast = 1;
|
||||
}
|
||||
if (ctrl->subchannel && !ctrl->bri)
|
||||
res = send_message(ctrl, c, Q931_SETUP, gr303_setup_ies);
|
||||
else if (c->cis_call)
|
||||
@@ -4877,13 +5039,9 @@ int q931_setup(struct pri *ctrl, q931_call *c, struct pri_sr *req)
|
||||
UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_CALL_INITIATED);
|
||||
c->peercallstate = Q931_CALL_STATE_CALL_PRESENT;
|
||||
c->t303_expirycnt = 0;
|
||||
if (BRI_NT_PTMP(ctrl)) {
|
||||
c->outboundbroadcast = 1;
|
||||
}
|
||||
start_t303(c);
|
||||
}
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
static int release_complete_ies[] = { Q931_IE_USER_USER, -1 };
|
||||
@@ -5379,6 +5537,12 @@ static void pri_fake_clearing(void *data)
|
||||
struct q931_call *c = data;
|
||||
struct pri *ctrl = c->pri;
|
||||
|
||||
/*
|
||||
* We cannot clear the retranstimer id because we are called by t303_expiry also.
|
||||
* Fortunately, it doesn't matter because pri_internal_clear() will stop it if
|
||||
* it was actually running.
|
||||
*/
|
||||
//c->retranstimer = 0;
|
||||
c->performing_fake_clearing = 1;
|
||||
if (pri_internal_clear(c) == Q931_RES_HAVEEVENT)
|
||||
ctrl->schedev = 1;
|
||||
@@ -5386,6 +5550,7 @@ static void pri_fake_clearing(void *data)
|
||||
|
||||
static void pri_create_fake_clearing(struct q931_call *c, struct pri *master)
|
||||
{
|
||||
/* Point to the master so the timeout event can come out. */
|
||||
c->pri = master;
|
||||
|
||||
pri_schedule_del(master, c->retranstimer);
|
||||
@@ -5640,7 +5805,9 @@ static int prepare_to_handle_maintenance_message(struct pri *ctrl, q931_mh *mh,
|
||||
c->changestatus = -1;
|
||||
break;
|
||||
default:
|
||||
pri_error(ctrl, "!! Don't know how to pre-handle maintenance message type '%d'\n", mh->msg);
|
||||
pri_error(ctrl,
|
||||
"!! Don't know how to pre-handle maintenance message type '0x%X'\n",
|
||||
mh->msg);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -5789,13 +5956,13 @@ static int prepare_to_handle_q931_message(struct pri *ctrl, q931_mh *mh, q931_ca
|
||||
case Q931_SUSPEND:
|
||||
case Q931_SUSPEND_ACKNOWLEDGE:
|
||||
case Q931_SUSPEND_REJECT:
|
||||
pri_error(ctrl, "!! Not yet handling pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
|
||||
pri_error(ctrl, "!! Not yet handling pre-handle message type %s (0x%X)\n",
|
||||
msg2str(mh->msg), mh->msg);
|
||||
/* Fall through */
|
||||
default:
|
||||
pri_error(ctrl, "!! Don't know how to pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
|
||||
pri_error(ctrl, "!! Don't know how to pre-handle message type %s (0x%X)\n",
|
||||
msg2str(mh->msg), mh->msg);
|
||||
q931_status(ctrl,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST);
|
||||
if (c->newcall)
|
||||
pri_destroycall(ctrl, c);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -5932,8 +6099,6 @@ int q931_receive(struct pri *ctrl, int tei, q931_h *h, int len)
|
||||
int allow_posthandle;
|
||||
|
||||
memset(last_ie, 0, sizeof(last_ie));
|
||||
if (ctrl->debug & PRI_DEBUG_Q931_DUMP)
|
||||
q931_dump(ctrl, tei, h, len, 0);
|
||||
#ifdef LIBPRI_COUNTERS
|
||||
ctrl->q931_rxcount++;
|
||||
#endif
|
||||
@@ -6002,7 +6167,18 @@ int q931_receive(struct pri *ctrl, int tei, q931_h *h, int len)
|
||||
/* Unknown protocol discriminator but we will treat it as Q.931 anyway. */
|
||||
case GR303_PROTOCOL_DISCRIMINATOR:
|
||||
case Q931_PROTOCOL_DISCRIMINATOR:
|
||||
prepare_to_handle_q931_message(ctrl, mh, c);
|
||||
if (prepare_to_handle_q931_message(ctrl, mh, c)) {
|
||||
/* Discard message. We don't know how to handle it. */
|
||||
if (!c->master_call->outboundbroadcast && c->newcall) {
|
||||
/*
|
||||
* Destroy new non-subcalls immediately. Let the normal
|
||||
* disconnect/destruction of subcalls happen when there is a
|
||||
* winner.
|
||||
*/
|
||||
pri_destroycall(ctrl, c);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
q931_clr_subcommands(ctrl);
|
||||
@@ -6179,7 +6355,8 @@ static int post_handle_maintenance_message(struct pri *ctrl, int protodisc, stru
|
||||
return Q931_RES_HAVEEVENT;
|
||||
}
|
||||
|
||||
pri_error(ctrl, "!! Don't know how to post-handle maintenance message type %d\n", mh->msg);
|
||||
pri_error(ctrl, "!! Don't know how to post-handle maintenance message type 0x%X\n",
|
||||
mh->msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -6830,9 +7007,20 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
||||
q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
|
||||
break;
|
||||
}
|
||||
if (c->ourcallstate == Q931_CALL_STATE_ACTIVE) {
|
||||
q931_status(ctrl, c, PRI_CAUSE_WRONG_MESSAGE);
|
||||
switch (c->ourcallstate) {
|
||||
case Q931_CALL_STATE_CALL_INITIATED:
|
||||
case Q931_CALL_STATE_OVERLAP_SENDING:
|
||||
case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
|
||||
case Q931_CALL_STATE_CALL_DELIVERED:
|
||||
case Q931_CALL_STATE_CALL_PRESENT:
|
||||
case Q931_CALL_STATE_CALL_RECEIVED:
|
||||
case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
|
||||
case Q931_CALL_STATE_OVERLAP_RECEIVING:
|
||||
/* Accept CONNECT in these states. */
|
||||
break;
|
||||
default:
|
||||
q931_status(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
|
||||
return 0;
|
||||
}
|
||||
UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_ACTIVE);
|
||||
c->peercallstate = Q931_CALL_STATE_CONNECT_REQUEST;
|
||||
@@ -6852,7 +7040,6 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
||||
if (c->cis_auto_disconnect && c->cis_call) {
|
||||
/* Make sure WE release when we initiate a signalling only connection */
|
||||
q931_hangup(ctrl, c, PRI_CAUSE_NORMAL_CLEARING);
|
||||
break;
|
||||
} else {
|
||||
c->incoming_ct_state = INCOMING_CT_STATE_IDLE;
|
||||
|
||||
@@ -6865,6 +7052,7 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
||||
|
||||
return Q931_RES_HAVEEVENT;
|
||||
}
|
||||
break;
|
||||
case Q931_FACILITY:
|
||||
if (c->newcall) {
|
||||
q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
|
||||
@@ -6958,16 +7146,24 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
||||
if ((ctrl->debug & PRI_DEBUG_Q931_ANOMALY) &&
|
||||
(c->cause != PRI_CAUSE_INTERWORKING))
|
||||
pri_error(ctrl, "Received unsolicited status: %s\n", pri_cause2str(c->cause));
|
||||
/* Workaround for S-12 ver 7.3 - it responds for invalid/non-implemented IEs at SETUP with null call state */
|
||||
if (
|
||||
#if 0
|
||||
if (!c->sugcallstate && (c->ourcallstate != Q931_CALL_STATE_CALL_INITIATED)) {
|
||||
/*
|
||||
* Workaround for S-12 ver 7.3 - it responds to
|
||||
* invalid/non-implemented IEs in SETUP with NULL call state.
|
||||
*/
|
||||
!c->sugcallstate && (c->ourcallstate != Q931_CALL_STATE_CALL_INITIATED)
|
||||
#else
|
||||
/* Remove "workaround" since it breaks certification testing. If we receive a STATUS message of call state
|
||||
* NULL and we are not in the call state NULL we must clear resources and return to the call state to pass
|
||||
* testing. See section 5.8.11 of Q.931 */
|
||||
/*
|
||||
* Remove "workaround" since it breaks certification testing. If
|
||||
* we receive a STATUS message of call state NULL and we are not
|
||||
* in the call state NULL we must clear resources and return to
|
||||
* the call state to pass testing. See section 5.8.11 of Q.931.
|
||||
*/
|
||||
|
||||
if (!c->sugcallstate) {
|
||||
!c->sugcallstate
|
||||
#endif
|
||||
) {
|
||||
ctrl->ev.hangup.subcmds = &ctrl->subcmds;
|
||||
ctrl->ev.hangup.channel = q931_encode_channel(c);
|
||||
ctrl->ev.hangup.cause = c->cause;
|
||||
@@ -7515,13 +7711,21 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
||||
case Q931_SUSPEND:
|
||||
case Q931_SUSPEND_ACKNOWLEDGE:
|
||||
case Q931_SUSPEND_REJECT:
|
||||
pri_error(ctrl, "!! Not yet handling post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
|
||||
pri_error(ctrl, "!! Not yet handling post-handle message type %s (0x%X)\n",
|
||||
msg2str(mh->msg), mh->msg);
|
||||
/* Fall through */
|
||||
default:
|
||||
pri_error(ctrl, "!! Don't know how to post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
|
||||
pri_error(ctrl, "!! Don't know how to post-handle message type %s (0x%X)\n",
|
||||
msg2str(mh->msg), mh->msg);
|
||||
q931_status(ctrl,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST);
|
||||
if (c->newcall)
|
||||
if (!c->master_call->outboundbroadcast && c->newcall) {
|
||||
/*
|
||||
* Destroy new non-subcalls immediately. Let the normal
|
||||
* disconnect/destruction of subcalls happen when there is a
|
||||
* winner.
|
||||
*/
|
||||
pri_destroycall(ctrl, c);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -7545,6 +7749,18 @@ static int pri_internal_clear(void *data)
|
||||
|
||||
UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_NULL);
|
||||
c->peercallstate = Q931_CALL_STATE_NULL;
|
||||
|
||||
if (c->master_call->outboundbroadcast
|
||||
&& c == q931_find_winning_call(c)) {
|
||||
/* Pass the hangup cause to the master_call. */
|
||||
c->master_call->cause = c->cause;
|
||||
|
||||
/* Declare this winning subcall to no longer be the winner and destroy it. */
|
||||
c->master_call->pri_winner = -1;
|
||||
q931_destroycall(ctrl, c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
q931_clr_subcommands(ctrl);
|
||||
ctrl->ev.hangup.subcmds = &ctrl->subcmds;
|
||||
ctrl->ev.hangup.channel = q931_encode_channel(c);
|
||||
@@ -7581,9 +7797,15 @@ static void pri_dl_down_timeout(void *data)
|
||||
{
|
||||
struct q931_call *c = data;
|
||||
struct pri *ctrl = c->pri;
|
||||
if (ctrl->debug & PRI_DEBUG_Q931_STATE)
|
||||
pri_message(ctrl, DBGHEAD "Timed out waiting for data link re-establishment\n", DBGINFO);
|
||||
|
||||
/* Point to the master so the timeout event can come out. */
|
||||
ctrl = PRI_MASTER(ctrl);
|
||||
c->pri = ctrl;
|
||||
|
||||
if (ctrl->debug & PRI_DEBUG_Q931_STATE)
|
||||
pri_message(ctrl, "T309 timed out waiting for data link re-establishment\n");
|
||||
|
||||
c->retranstimer = 0;
|
||||
c->cause = PRI_CAUSE_DESTINATION_OUT_OF_ORDER;
|
||||
if (pri_internal_clear(c) == Q931_RES_HAVEEVENT)
|
||||
ctrl->schedev = 1;
|
||||
@@ -7594,94 +7816,292 @@ static void pri_dl_down_cancelcall(void *data)
|
||||
{
|
||||
struct q931_call *c = data;
|
||||
struct pri *ctrl = c->pri;
|
||||
if (ctrl->debug & PRI_DEBUG_Q931_STATE)
|
||||
pri_message(ctrl, DBGHEAD "Cancel non active call after data link failure\n", DBGINFO);
|
||||
|
||||
/* Point to the master so the timeout event can come out. */
|
||||
ctrl = PRI_MASTER(ctrl);
|
||||
c->pri = ctrl;
|
||||
|
||||
if (ctrl->debug & PRI_DEBUG_Q931_STATE)
|
||||
pri_message(ctrl, "Cancel call after data link failure\n");
|
||||
|
||||
c->retranstimer = 0;
|
||||
c->cause = PRI_CAUSE_DESTINATION_OUT_OF_ORDER;
|
||||
if (pri_internal_clear(c) == Q931_RES_HAVEEVENT)
|
||||
ctrl->schedev = 1;
|
||||
}
|
||||
|
||||
/* Receive an indication from Layer 2 */
|
||||
void q931_dl_indication(struct pri *ctrl, int event)
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Convert the DL event to a string.
|
||||
*
|
||||
* \param event Data-link event to convert to a string.
|
||||
*
|
||||
* \return DL event string
|
||||
*/
|
||||
static const char *q931_dl_event2str(enum Q931_DL_EVENT event)
|
||||
{
|
||||
const char *str;
|
||||
|
||||
str = "Unknown";
|
||||
switch (event) {
|
||||
case Q931_DL_EVENT_NONE:
|
||||
str = "Q931_DL_EVENT_NONE";
|
||||
break;
|
||||
case Q931_DL_EVENT_DL_ESTABLISH_IND:
|
||||
str = "Q931_DL_EVENT_DL_ESTABLISH_IND";
|
||||
break;
|
||||
case Q931_DL_EVENT_DL_ESTABLISH_CONFIRM:
|
||||
str = "Q931_DL_EVENT_DL_ESTABLISH_CONFIRM";
|
||||
break;
|
||||
case Q931_DL_EVENT_DL_RELEASE_IND:
|
||||
str = "Q931_DL_EVENT_DL_RELEASE_IND";
|
||||
break;
|
||||
case Q931_DL_EVENT_DL_RELEASE_CONFIRM:
|
||||
str = "Q931_DL_EVENT_DL_RELEASE_CONFIRM";
|
||||
break;
|
||||
case Q931_DL_EVENT_TEI_REMOVAL:
|
||||
str = "Q931_DL_EVENT_TEI_REMOVAL";
|
||||
break;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Receive a DL event from layer 2.
|
||||
*
|
||||
* \param link Q.921 link event occurred on.
|
||||
* \param event Data-link event reporting.
|
||||
*
|
||||
* \return Nothing
|
||||
*/
|
||||
void q931_dl_event(struct pri *link, enum Q931_DL_EVENT event)
|
||||
{
|
||||
struct q931_call *cur;
|
||||
struct q931_call *winner;
|
||||
struct q931_call *call;
|
||||
struct pri *ctrl;
|
||||
int idx;
|
||||
|
||||
/* Just return if T309 is not enabled. */
|
||||
if (!ctrl || ctrl->timers[PRI_TIMER_T309] < 0)
|
||||
if (!link) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Find the master - He has the call pool */
|
||||
ctrl = PRI_MASTER(link);
|
||||
|
||||
if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
|
||||
pri_message(ctrl, "TEI=%d DL event: %s(%d)\n", link->tei,
|
||||
q931_dl_event2str(event), event);
|
||||
}
|
||||
|
||||
if (BRI_TE_PTMP(ctrl)) {
|
||||
/* The link is always the master */
|
||||
link = ctrl;
|
||||
}
|
||||
|
||||
switch (event) {
|
||||
case PRI_EVENT_DCHAN_DOWN:
|
||||
if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
|
||||
pri_message(ctrl, DBGHEAD "link is DOWN\n", DBGINFO);
|
||||
case Q931_DL_EVENT_TEI_REMOVAL:
|
||||
if (!BRI_NT_PTMP(ctrl)) {
|
||||
/* Only NT PTMP has anything to worry about when the TEI is removed. */
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* For NT PTMP, this deviation from the specifications is needed
|
||||
* because we have no way to re-associate any T309 calls on the
|
||||
* removed TEI.
|
||||
*/
|
||||
for (cur = *ctrl->callpool; cur; cur = cur->next) {
|
||||
if (!(cur->cr & ~Q931_CALL_REFERENCE_FLAG)) {
|
||||
/* Don't do anything on the global call reference call record. */
|
||||
continue;
|
||||
} else if (cur->ourcallstate == Q931_CALL_STATE_ACTIVE) {
|
||||
/* For a call in Active state, activate T309 only if there is no timer already running. */
|
||||
if (!cur->retranstimer) {
|
||||
if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
|
||||
pri_message(ctrl,
|
||||
DBGHEAD "activate T309 for call %d on channel %d\n", DBGINFO,
|
||||
cur->cr, cur->channelno);
|
||||
}
|
||||
if (cur->outboundbroadcast) {
|
||||
/* Does this master call have a subcall on the link that went down? */
|
||||
call = NULL;
|
||||
for (idx = 0; idx < ARRAY_LEN(cur->subcalls); ++idx) {
|
||||
if (cur->subcalls[idx] && cur->subcalls[idx]->pri == link) {
|
||||
/* This subcall is on the link that went down. */
|
||||
call = cur->subcalls[idx];
|
||||
break;
|
||||
}
|
||||
cur->retranstimer = pri_schedule_event(ctrl, ctrl->timers[PRI_TIMER_T309], pri_dl_down_timeout, cur);
|
||||
}
|
||||
} else if (cur->ourcallstate != Q931_CALL_STATE_NULL) {
|
||||
/* For a call that is not in Active state, schedule internal clearing of the call 'ASAP' (delay 0). */
|
||||
if (!call) {
|
||||
/* No subcall is on the link that went down. */
|
||||
continue;
|
||||
}
|
||||
} else if (cur->pri != link) {
|
||||
/* This call is not on the link that went down. */
|
||||
continue;
|
||||
} else {
|
||||
call = cur;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: We are gambling that no T309 timer's have had a chance
|
||||
* to expire. They should not expire since we are either called
|
||||
* immediately after the Q931_DL_EVENT_DL_RELEASE_xxx or after a
|
||||
* timeout of 0.
|
||||
*/
|
||||
if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
|
||||
pri_message(ctrl, "Cancel call cref=%d on channel %d in state %d (%s)\n",
|
||||
call->cr, call->channelno, call->ourcallstate,
|
||||
q931_call_state_str(call->ourcallstate));
|
||||
}
|
||||
call->pri = ctrl;/* Point to a safer place until the call is destroyed. */
|
||||
pri_schedule_del(ctrl, call->retranstimer);
|
||||
call->retranstimer = pri_schedule_event(ctrl, 0, pri_dl_down_cancelcall,
|
||||
call);
|
||||
}
|
||||
break;
|
||||
case Q931_DL_EVENT_DL_RELEASE_IND:
|
||||
case Q931_DL_EVENT_DL_RELEASE_CONFIRM:
|
||||
for (cur = *ctrl->callpool; cur; cur = cur->next) {
|
||||
if (!(cur->cr & ~Q931_CALL_REFERENCE_FLAG)) {
|
||||
/* Don't do anything on the global call reference call record. */
|
||||
continue;
|
||||
}
|
||||
if (cur->outboundbroadcast) {
|
||||
/* Does this master call have a subcall on the link that went down? */
|
||||
call = NULL;
|
||||
for (idx = 0; idx < ARRAY_LEN(cur->subcalls); ++idx) {
|
||||
if (cur->subcalls[idx] && cur->subcalls[idx]->pri == link) {
|
||||
/* This subcall is on the link that went down. */
|
||||
call = cur->subcalls[idx];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!call) {
|
||||
/* No subcall is on the link that went down. */
|
||||
continue;
|
||||
}
|
||||
} else if (cur->pri != link) {
|
||||
/* This call is not on the link that went down. */
|
||||
continue;
|
||||
} else {
|
||||
call = cur;
|
||||
}
|
||||
switch (call->ourcallstate) {
|
||||
case Q931_CALL_STATE_ACTIVE:
|
||||
/* NOTE: Only a winning subcall can get to the active state. */
|
||||
if (ctrl->nfas) {
|
||||
/*
|
||||
* The upper layer should handle T309 for NFAS since the calls
|
||||
* could be maintained by a backup D channel if the B channel
|
||||
* for the call did not go into alarm.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* For a call in Active state, activate T309 only if there is
|
||||
* no timer already running.
|
||||
*
|
||||
* NOTE: cur != call when we have a winning subcall.
|
||||
*/
|
||||
if (!cur->retranstimer || !call->retranstimer) {
|
||||
if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
|
||||
pri_message(ctrl, "Start T309 for call cref=%d on channel %d\n",
|
||||
call->cr, call->channelno);
|
||||
}
|
||||
call->retranstimer = pri_schedule_event(ctrl,
|
||||
ctrl->timers[PRI_TIMER_T309], pri_dl_down_timeout, call);
|
||||
}
|
||||
break;
|
||||
case Q931_CALL_STATE_NULL:
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* For a call that is not in Active state, schedule internal
|
||||
* clearing of the call 'ASAP' (delay 0).
|
||||
*
|
||||
* NOTE: We are killing NFAS calls that are not connected yet
|
||||
* because there are likely messages in flight when this link
|
||||
* went down that could leave the call in an unknown/stuck state.
|
||||
*/
|
||||
if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
|
||||
pri_message(ctrl,
|
||||
DBGHEAD "cancel call %d on channel %d in state %d (%s)\n", DBGINFO,
|
||||
cur->cr, cur->channelno, cur->ourcallstate,
|
||||
q931_call_state_str(cur->ourcallstate));
|
||||
"Cancel call cref=%d on channel %d in state %d (%s)\n",
|
||||
call->cr, call->channelno, call->ourcallstate,
|
||||
q931_call_state_str(call->ourcallstate));
|
||||
}
|
||||
pri_schedule_del(ctrl, cur->retranstimer);
|
||||
cur->retranstimer = pri_schedule_event(ctrl, 0, pri_dl_down_cancelcall, cur);
|
||||
if (cur->outboundbroadcast) {
|
||||
/* Simply destroy non-winning subcalls. */
|
||||
q931_destroycall(ctrl, call);
|
||||
continue;
|
||||
}
|
||||
pri_schedule_del(ctrl, call->retranstimer);
|
||||
call->retranstimer = pri_schedule_event(ctrl, 0, pri_dl_down_cancelcall,
|
||||
call);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PRI_EVENT_DCHAN_UP:
|
||||
if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
|
||||
pri_message(ctrl, DBGHEAD "link is UP\n", DBGINFO);
|
||||
}
|
||||
case Q931_DL_EVENT_DL_ESTABLISH_IND:
|
||||
case Q931_DL_EVENT_DL_ESTABLISH_CONFIRM:
|
||||
for (cur = *ctrl->callpool; cur; cur = cur->next) {
|
||||
if (!(cur->cr & ~Q931_CALL_REFERENCE_FLAG)) {
|
||||
/* Don't do anything on the global call reference call record. */
|
||||
continue;
|
||||
} else if (cur->ourcallstate == Q931_CALL_STATE_ACTIVE && cur->retranstimer) {
|
||||
if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
|
||||
pri_message(ctrl,
|
||||
DBGHEAD "cancel T309 for call %d on channel %d\n", DBGINFO,
|
||||
cur->cr, cur->channelno);
|
||||
}
|
||||
if (cur->outboundbroadcast) {
|
||||
/* Does this master call have a subcall on the link that came up? */
|
||||
call = NULL;
|
||||
for (idx = 0; idx < ARRAY_LEN(cur->subcalls); ++idx) {
|
||||
if (cur->subcalls[idx] && cur->subcalls[idx]->pri == link) {
|
||||
/* This subcall is on the link that came up. */
|
||||
call = cur->subcalls[idx];
|
||||
break;
|
||||
}
|
||||
}
|
||||
pri_schedule_del(ctrl, cur->retranstimer);
|
||||
cur->retranstimer = 0;
|
||||
winner = q931_find_winning_call(cur);
|
||||
if (winner) {
|
||||
q931_status(ctrl, winner, PRI_CAUSE_NORMAL_UNSPECIFIED);
|
||||
if (!call) {
|
||||
/* No subcall is on the link that came up. */
|
||||
continue;
|
||||
}
|
||||
} else if (cur->pri != link) {
|
||||
/* This call is not on the link that came up. */
|
||||
continue;
|
||||
} else {
|
||||
call = cur;
|
||||
}
|
||||
switch (call->ourcallstate) {
|
||||
case Q931_CALL_STATE_ACTIVE:
|
||||
/* NOTE: Only a winning subcall can get to the active state. */
|
||||
if (pri_schedule_check(ctrl, call->retranstimer, pri_dl_down_timeout, call)) {
|
||||
if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
|
||||
pri_message(ctrl, "Stop T309 for call cref=%d on channel %d\n",
|
||||
call->cr, call->channelno);
|
||||
}
|
||||
pri_schedule_del(ctrl, call->retranstimer);
|
||||
call->retranstimer = 0;
|
||||
}
|
||||
q931_status(ctrl, call, PRI_CAUSE_NORMAL_UNSPECIFIED);
|
||||
break;
|
||||
case Q931_CALL_STATE_NULL:
|
||||
case Q931_CALL_STATE_DISCONNECT_REQUEST:
|
||||
case Q931_CALL_STATE_DISCONNECT_INDICATION:
|
||||
case Q931_CALL_STATE_RELEASE_REQUEST:
|
||||
break;
|
||||
default:
|
||||
if (event == Q931_DL_EVENT_DL_ESTABLISH_CONFIRM) {
|
||||
/*
|
||||
* Lets not send a STATUS message for this call as we
|
||||
* requested the link to be established as a likely
|
||||
* result of this call.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
} else if (cur->ourcallstate != Q931_CALL_STATE_NULL &&
|
||||
cur->ourcallstate != Q931_CALL_STATE_DISCONNECT_REQUEST &&
|
||||
cur->ourcallstate != Q931_CALL_STATE_DISCONNECT_INDICATION &&
|
||||
cur->ourcallstate != Q931_CALL_STATE_RELEASE_REQUEST) {
|
||||
/*
|
||||
* The STATUS message sent here is not required by Q.931,
|
||||
* but it may help anyway.
|
||||
* This looks like a new call started while the link was down.
|
||||
*/
|
||||
winner = q931_find_winning_call(cur);
|
||||
if (winner) {
|
||||
q931_status(ctrl, winner, PRI_CAUSE_NORMAL_UNSPECIFIED);
|
||||
}
|
||||
q931_status(ctrl, call, PRI_CAUSE_NORMAL_UNSPECIFIED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pri_message(ctrl, DBGHEAD "unexpected event %d.\n", DBGINFO, event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
45
rose.c
45
rose.c
@@ -470,6 +470,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 +494,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 +518,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) }
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
98
rosetest.c
98
rosetest.c
@@ -2132,6 +2132,80 @@ static unsigned char rose_qsig_multiple_msg[] = {
|
||||
/* *INDENT-ON* */
|
||||
};
|
||||
|
||||
static unsigned char rose_qsig_name_alt_encode_msg[] = {
|
||||
/* *INDENT-OFF* */
|
||||
/*
|
||||
* Context Specific/C [10 0x0A] <AA> Len:6 <06>
|
||||
* Context Specific [0 0x00] <80> Len:1 <01>
|
||||
* <00> - "~"
|
||||
* Context Specific [2 0x02] <82> Len:1 <01>
|
||||
* <00> - "~"
|
||||
* Context Specific [11 0x0B] <8B> Len:1 <01>
|
||||
* <00> - "~"
|
||||
* Context Specific/C [1 0x01] <A1> Len:21 <15>
|
||||
* Integer(2 0x02) <02> Len:1 <01>
|
||||
* <1D> - "~"
|
||||
* Integer(2 0x02) <02> Len:1 <01>
|
||||
* <00> - "~"
|
||||
* Sequence/C(48 0x30) <30> Len:13 <0D>
|
||||
* Context Specific [0 0x00] <80> Len:11 <0B>
|
||||
* <55 54 49 4C 49 54 59 20-54 45 4C> - "UTILITY TEL"
|
||||
*/
|
||||
0x9F,
|
||||
0xAA, 0x06,
|
||||
0x80, 0x01,
|
||||
0x00,
|
||||
0x82, 0x01,
|
||||
0x00,
|
||||
0x8B, 0x01,
|
||||
0x00,
|
||||
0xA1, 0x15,
|
||||
0x02, 0x01,
|
||||
0x1D,
|
||||
0x02, 0x01,
|
||||
0x00,
|
||||
0x30, 0x0D,
|
||||
0x80, 0x0B,
|
||||
0x55, 0x54, 0x49, 0x4C, 0x49, 0x54, 0x59, 0x20, 0x54, 0x45, 0x4C
|
||||
/* *INDENT-ON* */
|
||||
};
|
||||
|
||||
static unsigned char rose_qsig_name_2nd_encode_msg[] = {
|
||||
/* *INDENT-OFF* */
|
||||
/*
|
||||
* Context Specific/C [10 0x0A] <AA> Len:6 <06>
|
||||
* Context Specific [0 0x00] <80> Len:1 <01>
|
||||
* <00> - "~"
|
||||
* Context Specific [2 0x02] <82> Len:1 <01>
|
||||
* <00> - "~"
|
||||
* Context Specific [11 0x0B] <8B> Len:1 <01>
|
||||
* <00> - "~"
|
||||
* Context Specific/C [1 0x01] <A1> Len:26 <1A>
|
||||
* Integer(2 0x02) <02> Len:1 <01>
|
||||
* <40> - "@"
|
||||
* OID(6 0x06) <06> Len:4 <04>
|
||||
* <2B 0C 09 00> - "+~~~"
|
||||
* Context Specific [0 0x00] <80> Len:15 <0F>
|
||||
* <4D 6F 64 65 6D 20 44 69-73 63 6F 42 61 6C 6C> - "Modem DiscoBall"
|
||||
*/
|
||||
0x91,
|
||||
0xaa, 0x06,
|
||||
0x80, 0x01,
|
||||
0x00,
|
||||
0x82, 0x01,
|
||||
0x00,
|
||||
0x8b, 0x01,
|
||||
0x00,
|
||||
0xa1, 0x1a,
|
||||
0x02, 0x01,
|
||||
0x40,
|
||||
0x06, 0x04,
|
||||
0x2b, 0x0c, 0x09, 0x00,
|
||||
0x80, 0x0f,
|
||||
0x4d, 0x6f, 0x64, 0x65, 0x6d, 0x20, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x42, 0x61, 0x6c, 0x6c
|
||||
/* *INDENT-ON* */
|
||||
};
|
||||
|
||||
|
||||
static const struct rose_message rose_dms100_msgs[] = {
|
||||
/* *INDENT-OFF* */
|
||||
@@ -2318,6 +2392,7 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
unsigned index;
|
||||
unsigned offset;
|
||||
const char *str;
|
||||
static struct pri dummy_ctrl;
|
||||
|
||||
pri_set_message(rose_pri_message);
|
||||
@@ -2326,6 +2401,9 @@ int main(int argc, char *argv[])
|
||||
memset(&dummy_ctrl, 0, sizeof(dummy_ctrl));
|
||||
dummy_ctrl.debug = PRI_DEBUG_APDU;
|
||||
|
||||
/* For sanity specify what version of libpri we are testing. */
|
||||
pri_error(&dummy_ctrl, "libpri version tested: %s\n", pri_get_version());
|
||||
|
||||
offset = 0;
|
||||
pri_message(&dummy_ctrl, "Encode/decode message(s)\n");
|
||||
if (argc <= 1) {
|
||||
@@ -2420,12 +2498,23 @@ int main(int argc, char *argv[])
|
||||
rose_test_exception(&dummy_ctrl, "Multiple component messages",
|
||||
rose_qsig_multiple_msg, sizeof(rose_qsig_multiple_msg));
|
||||
|
||||
rose_test_exception(&dummy_ctrl, "Alternate name encoded messages",
|
||||
rose_qsig_name_alt_encode_msg, sizeof(rose_qsig_name_alt_encode_msg));
|
||||
|
||||
rose_test_exception(&dummy_ctrl, "2nd edition name encoded messages",
|
||||
rose_qsig_name_2nd_encode_msg, sizeof(rose_qsig_name_2nd_encode_msg));
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
||||
pri_message(&dummy_ctrl, "\n\n"
|
||||
"List of operation codes:\n");
|
||||
for (index = 0; index < ROSE_Num_Operation_Codes; ++index) {
|
||||
pri_message(&dummy_ctrl, "%d: %s\n", index, rose_operation2str(index));
|
||||
str = rose_operation2str(index);
|
||||
if (!strncmp(str, "Invalid code:", 13)) {
|
||||
pri_error(&dummy_ctrl, "%d: %s\n", index, str);
|
||||
} else {
|
||||
pri_message(&dummy_ctrl, "%d: %s\n", index, str);
|
||||
}
|
||||
}
|
||||
pri_message(&dummy_ctrl, "\n\n"
|
||||
"************************************************************\n");
|
||||
@@ -2435,7 +2524,12 @@ int main(int argc, char *argv[])
|
||||
pri_message(&dummy_ctrl, "\n\n"
|
||||
"List of error codes:\n");
|
||||
for (index = 0; index < ROSE_ERROR_Num_Codes; ++index) {
|
||||
pri_message(&dummy_ctrl, "%d: %s\n", index, rose_error2str(index));
|
||||
str = rose_error2str(index);
|
||||
if (!strncmp(str, "Invalid code:", 13)) {
|
||||
pri_error(&dummy_ctrl, "%d: %s\n", index, str);
|
||||
} else {
|
||||
pri_message(&dummy_ctrl, "%d: %s\n", index, str);
|
||||
}
|
||||
}
|
||||
pri_message(&dummy_ctrl, "\n\n"
|
||||
"************************************************************\n");
|
||||
|
||||
Reference in New Issue
Block a user