Compare commits

...

14 Commits

Author SHA1 Message Date
Leif Madsen
271a4f3067 Drop incorrect summary files.
git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.4.11.5@2142 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-11-18 21:02:58 +00:00
Leif Madsen
64ae283190 Importing release summary for 1.4.11.5 release.
git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.4.11.5@2141 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-11-18 20:24:34 +00:00
Richard Mudgett
692697d39b Update ChangeLog.
git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.4.11.5@2140 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-11-17 21:52:46 +00:00
Richard Mudgett
9a7715a09d 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.
..........


git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.4.11.5@2139 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-11-17 21:32:40 +00:00
Richard Mudgett
a9696d095c 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
..........


git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.4.11.5@2138 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-11-17 21:30:31 +00:00
Richard Mudgett
ea9b8059de 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)
..........


git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.4.11.5@2137 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-11-17 21:28:12 +00:00
Richard Mudgett
ee25bdfb5e 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
..........


git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.4.11.5@2136 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-11-17 21:26:30 +00:00
Richard Mudgett
2fd3fff781 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.
..........


git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.4.11.5@2135 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-11-17 21:24:21 +00:00
Richard Mudgett
1b11116f18 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
..........


git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.4.11.5@2134 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-11-17 21:22:45 +00:00
Richard Mudgett
52c6b7289d 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
..........


git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.4.11.5@2133 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-11-17 21:20:48 +00:00
Richard Mudgett
3cb1f6fbce 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)
..........


git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.4.11.5@2132 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-11-17 21:19:19 +00:00
Richard Mudgett
2ab04a7663 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().
..........


git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.4.11.5@2131 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-11-17 21:17:47 +00:00
Leif Madsen
915d423ffc update .version and changelog
git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.4.11.5@2127 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-11-17 20:52:42 +00:00
Leif Madsen
a3a73a30c9 Create libpri 1.4.11.5 from 1.4.11.4
git-svn-id: https://origsvn.digium.com/svn/libpri/tags/1.4.11.5@2126 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2010-11-17 20:51:38 +00:00
9 changed files with 749 additions and 139 deletions

View File

@@ -1 +1 @@
1.4.11.4
1.4.11.5

120
ChangeLog
View File

@@ -1,3 +1,123 @@
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.

113
pri.c
View File

@@ -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)
@@ -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;
@@ -1055,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);
@@ -1075,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);
@@ -1093,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);
}
@@ -1104,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);
@@ -1328,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]);
}
@@ -1344,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)
@@ -1494,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);
@@ -1502,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);
@@ -1510,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);
@@ -1518,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);
@@ -1526,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);
@@ -1534,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);
@@ -1542,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);
}
@@ -1562,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;
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
}

109
q921.c
View File

@@ -215,7 +215,7 @@ static void t202_expire(void *vpri)
case Q921_ESTABLISH_AWAITING_TEI:
q921_discard_iqueue(ctrl);
/* DL-RELEASE indication */
q931_dl_indication(ctrl, PRI_EVENT_DCHAN_DOWN);
q931_dl_event(ctrl, Q931_DL_EVENT_DL_RELEASE_IND);
break;
default:
break;
@@ -235,6 +235,16 @@ static void q921_tei_request(struct pri *ctrl)
t202_expire(ctrl);
}
static void q921_tei_remove(struct pri *ctrl, int tei)
{
/*
* Q.921 Section 5.3.2 says we should send the remove message
* twice, in case of message loss.
*/
q921_send_tei(ctrl, Q921_TEI_IDENTITY_REMOVE, 0, tei, 1);
q921_send_tei(ctrl, Q921_TEI_IDENTITY_REMOVE, 0, tei, 1);
}
static void q921_send_dm(struct pri *ctrl, int fbit)
{
q921_h h;
@@ -671,7 +681,7 @@ static void t200_expire(void *vpri)
q921_mdl_error(ctrl, 'G');
q921_setstate(ctrl, Q921_TEI_ASSIGNED);
/* DL-RELEASE indication */
q931_dl_indication(ctrl, PRI_EVENT_DCHAN_DOWN);
q931_dl_event(ctrl, Q931_DL_EVENT_DL_RELEASE_IND);
}
break;
case Q921_AWAITING_RELEASE:
@@ -682,6 +692,7 @@ static void t200_expire(void *vpri)
} else {
q921_mdl_error(ctrl, 'H');
/* DL-RELEASE confirm */
q931_dl_event(ctrl, Q931_DL_EVENT_DL_RELEASE_CONFIRM);
q921_setstate(ctrl, Q921_TEI_ASSIGNED);
}
break;
@@ -1280,6 +1291,7 @@ static void q921_clear_exception_conditions(struct pri *ctrl)
static pri_event * q921_sabme_rx(struct pri *ctrl, q921_h *h)
{
pri_event *res = NULL;
enum Q931_DL_EVENT delay_q931_dl_event;
switch (ctrl->q921_state) {
case Q921_TIMER_RECOVERY:
@@ -1292,25 +1304,35 @@ static pri_event * q921_sabme_rx(struct pri *ctrl, q921_h *h)
if (ctrl->v_s != ctrl->v_a) {
q921_discard_iqueue(ctrl);
/* DL-ESTABLISH indication */
q931_dl_indication(ctrl, PRI_EVENT_DCHAN_UP);
delay_q931_dl_event = Q931_DL_EVENT_DL_ESTABLISH_IND;
} else {
delay_q931_dl_event = Q931_DL_EVENT_NONE;
}
stop_t200(ctrl);
start_t203(ctrl);
ctrl->v_s = ctrl->v_a = ctrl->v_r = 0;
q921_setstate(ctrl, Q921_MULTI_FRAME_ESTABLISHED);
if (delay_q931_dl_event != Q931_DL_EVENT_NONE) {
/* Delayed because Q.931 could send STATUS messages. */
q931_dl_event(ctrl, delay_q931_dl_event);
}
break;
case Q921_TEI_ASSIGNED:
q921_send_ua(ctrl, h->u.p_f);
q921_clear_exception_conditions(ctrl);
ctrl->v_s = ctrl->v_a = ctrl->v_r = 0;
/* DL-ESTABLISH indication */
q931_dl_indication(ctrl, PRI_EVENT_DCHAN_UP);
delay_q931_dl_event = Q931_DL_EVENT_DL_ESTABLISH_IND;
if (PTP_MODE(ctrl)) {
ctrl->ev.gen.e = PRI_EVENT_DCHAN_UP;
res = &ctrl->ev;
}
start_t203(ctrl);
q921_setstate(ctrl, Q921_MULTI_FRAME_ESTABLISHED);
if (delay_q931_dl_event != Q931_DL_EVENT_NONE) {
/* Delayed because Q.931 could send STATUS messages. */
q931_dl_event(ctrl, delay_q931_dl_event);
}
break;
case Q921_AWAITING_ESTABLISHMENT:
q921_send_ua(ctrl, h->u.p_f);
@@ -1347,8 +1369,8 @@ static pri_event *q921_disc_rx(struct pri *ctrl, q921_h *h)
case Q921_TIMER_RECOVERY:
q921_discard_iqueue(ctrl);
q921_send_ua(ctrl, h->u.p_f);
/* DL-RELEASE Indication */
q931_dl_indication(ctrl, PRI_EVENT_DCHAN_DOWN);
/* DL-RELEASE indication */
q931_dl_event(ctrl, Q931_DL_EVENT_DL_RELEASE_IND);
stop_t200(ctrl);
if (ctrl->q921_state == Q921_MULTI_FRAME_ESTABLISHED)
stop_t203(ctrl);
@@ -1390,20 +1412,21 @@ static void q921_mdl_remove(struct pri *ctrl)
case Q921_AWAITING_ESTABLISHMENT:
q921_discard_iqueue(ctrl);
/* DL-RELEASE indication */
q931_dl_indication(ctrl, PRI_EVENT_DCHAN_DOWN);
q931_dl_event(ctrl, Q931_DL_EVENT_DL_RELEASE_IND);
stop_t200(ctrl);
q921_setstate(ctrl, Q921_TEI_UNASSIGNED);
break;
case Q921_AWAITING_RELEASE:
q921_discard_iqueue(ctrl);
/* DL-RELEASE confirm */
q931_dl_event(ctrl, Q931_DL_EVENT_DL_RELEASE_CONFIRM);
stop_t200(ctrl);
q921_setstate(ctrl, Q921_TEI_UNASSIGNED);
break;
case Q921_MULTI_FRAME_ESTABLISHED:
q921_discard_iqueue(ctrl);
/* DL-RELEASE indication */
q931_dl_indication(ctrl, PRI_EVENT_DCHAN_DOWN);
q931_dl_event(ctrl, Q931_DL_EVENT_DL_RELEASE_IND);
stop_t200(ctrl);
stop_t203(ctrl);
q921_setstate(ctrl, Q921_TEI_UNASSIGNED);
@@ -1411,7 +1434,7 @@ static void q921_mdl_remove(struct pri *ctrl)
case Q921_TIMER_RECOVERY:
q921_discard_iqueue(ctrl);
/* DL-RELEASE indication */
q931_dl_indication(ctrl, PRI_EVENT_DCHAN_DOWN);
q931_dl_event(ctrl, Q931_DL_EVENT_DL_RELEASE_IND);
stop_t200(ctrl);
q921_setstate(ctrl, Q921_TEI_UNASSIGNED);
break;
@@ -1421,6 +1444,8 @@ static void q921_mdl_remove(struct pri *ctrl)
return;
}
q931_dl_event(ctrl, Q931_DL_EVENT_TEI_REMOVAL);
/*
* Negate the TEI value so debug messages will display a
* negated TEI when it is actually unassigned.
@@ -1696,7 +1721,8 @@ static void q921_mdl_error(struct pri *ctrl, char error)
static pri_event *q921_ua_rx(struct pri *ctrl, q921_h *h)
{
pri_event * res = NULL;
pri_event *res = NULL;
enum Q931_DL_EVENT delay_q931_dl_event;
if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
pri_message(ctrl, "TEI=%d Got UA\n", ctrl->tei);
@@ -1718,15 +1744,17 @@ static pri_event *q921_ua_rx(struct pri *ctrl, q921_h *h)
break;
}
delay_q931_dl_event = Q931_DL_EVENT_NONE;
if (!ctrl->l3initiated) {
if (ctrl->v_s != ctrl->v_a) {
q921_discard_iqueue(ctrl);
/* return DL-ESTABLISH-INDICATION */
q931_dl_indication(ctrl, PRI_EVENT_DCHAN_UP);
/* DL-ESTABLISH indication */
delay_q931_dl_event = Q931_DL_EVENT_DL_ESTABLISH_IND;
}
} else {
ctrl->l3initiated = 0;
/* return DL-ESTABLISH-CONFIRM */
/* DL-ESTABLISH confirm */
delay_q931_dl_event = Q931_DL_EVENT_DL_ESTABLISH_CONFIRM;
}
if (PTP_MODE(ctrl)) {
@@ -1740,12 +1768,17 @@ static pri_event *q921_ua_rx(struct pri *ctrl, q921_h *h)
ctrl->v_r = ctrl->v_s = ctrl->v_a = 0;
q921_setstate(ctrl, Q921_MULTI_FRAME_ESTABLISHED);
if (delay_q931_dl_event != Q931_DL_EVENT_NONE) {
/* Delayed because Q.931 could send STATUS messages. */
q931_dl_event(ctrl, delay_q931_dl_event);
}
break;
case Q921_AWAITING_RELEASE:
if (!h->u.p_f) {
q921_mdl_error(ctrl, 'D');
} else {
/* return DL-RELEASE-CONFIRM */
/* DL-RELEASE confirm */
q931_dl_event(ctrl, Q931_DL_EVENT_DL_RELEASE_CONFIRM);
stop_t200(ctrl);
q921_setstate(ctrl, Q921_TEI_ASSIGNED);
}
@@ -2047,10 +2080,12 @@ static pri_event *q921_iframe_rx(struct pri *ctrl, q921_h *h, int len)
{
pri_event * eres = NULL;
int res = 0;
int delay_q931_receive;
switch (ctrl->q921_state) {
case Q921_TIMER_RECOVERY:
case Q921_MULTI_FRAME_ESTABLISHED:
delay_q931_receive = 0;
/* FIXME: Verify that it's a command ... */
if (ctrl->own_rx_busy) {
/* XXX: Note: There's a difference in th P/F between both states */
@@ -2060,19 +2095,20 @@ static pri_event *q921_iframe_rx(struct pri *ctrl, q921_h *h, int len)
ctrl->reject_exception = 0;
//res = q931_receive(PRI_MASTER(ctrl), ctrl->tei, (q931_h *)h->i.data, len - 4);
res = q931_receive(ctrl, ctrl->tei, (q931_h *)h->i.data, len - 4);
if (res != -1 && (res & Q931_RES_HAVEEVENT)) {
eres = &ctrl->ev;
/*
* Dump Q.931 message where Q.921 says to queue it to Q.931 so if
* Q.921 is dumping its frames they will be in the correct order.
*/
if (ctrl->debug & PRI_DEBUG_Q931_DUMP) {
q931_dump(ctrl, ctrl->tei, (q931_h *) h->i.data, len - 4, 0);
}
delay_q931_receive = 1;
if (h->i.p_f) {
q921_rr(ctrl, 1, 0);
ctrl->acknowledge_pending = 0;
} else {
if (!ctrl->acknowledge_pending) {
ctrl->acknowledge_pending = 1;
}
ctrl->acknowledge_pending = 1;
}
} else {
if (ctrl->reject_exception) {
@@ -2110,6 +2146,13 @@ static pri_event *q921_iframe_rx(struct pri *ctrl, q921_h *h, int len)
}
}
}
if (delay_q931_receive) {
/* Q.921 has finished processing the frame so we can give it to Q.931 now. */
res = q931_receive(ctrl, ctrl->tei, (q931_h *) h->i.data, len - 4);
if (res != -1 && (res & Q931_RES_HAVEEVENT)) {
eres = &ctrl->ev;
}
}
break;
case Q921_TEI_ASSIGNED:
case Q921_AWAITING_ESTABLISHMENT:
@@ -2151,7 +2194,7 @@ static pri_event *q921_dm_rx(struct pri *ctrl, q921_h *h)
q921_discard_iqueue(ctrl);
/* DL-RELEASE indication */
q931_dl_indication(ctrl, PRI_EVENT_DCHAN_DOWN);
q931_dl_event(ctrl, Q931_DL_EVENT_DL_RELEASE_IND);
stop_t200(ctrl);
q921_setstate(ctrl, Q921_TEI_ASSIGNED);
q921_restart_ptp_link_if_needed(ctrl);
@@ -2160,6 +2203,7 @@ static pri_event *q921_dm_rx(struct pri *ctrl, q921_h *h)
if (!h->u.p_f)
break;
/* DL-RELEASE confirm */
q931_dl_event(ctrl, Q931_DL_EVENT_DL_RELEASE_CONFIRM);
stop_t200(ctrl);
q921_setstate(ctrl, Q921_TEI_ASSIGNED);
break;
@@ -2342,6 +2386,9 @@ static pri_event *__q921_receive_qualified(struct pri *ctrl, q921_h *h, int len)
break;
case 0x00:
/* UI-frame */
if (ctrl->debug & PRI_DEBUG_Q931_DUMP) {
q931_dump(ctrl, ctrl->tei, (q931_h *) h->u.data, len - 3, 0);
}
res = q931_receive(ctrl, ctrl->tei, (q931_h *) h->u.data, len - 3);
if (res != -1 && (res & Q931_RES_HAVEEVENT)) {
ev = &ctrl->ev;
@@ -2418,9 +2465,7 @@ static pri_event *q921_handle_unmatched_frame(struct pri *ctrl, q921_h *h, int l
pri_message(ctrl, "Sending TEI release, in order to re-establish TEI state\n");
}
/* Q.921 says we should send the remove message twice, in case of link corruption */
q921_send_tei(ctrl, Q921_TEI_IDENTITY_REMOVE, 0, h->h.tei, 1);
q921_send_tei(ctrl, Q921_TEI_IDENTITY_REMOVE, 0, h->h.tei, 1);
q921_tei_remove(ctrl, h->h.tei);
}
return NULL;
@@ -2468,7 +2513,9 @@ static pri_event *__q921_receive(struct pri *ctrl, q921_h *h, int len)
} else {
ev = q921_handle_unmatched_frame(ctrl, h, len);
}
} else if (PTP_MODE(ctrl) && (h->h.sapi == ctrl->sapi) && (h->h.tei == ctrl->tei)) {
} else if (PTP_MODE(ctrl)
&& h->h.sapi == ctrl->sapi
&& (h->h.tei == ctrl->tei || h->h.tei == Q921_TEI_GROUP)) {
ev = __q921_receive_qualified(ctrl, h, len);
} else {
ev = NULL;
@@ -2517,6 +2564,16 @@ void q921_start(struct pri *ctrl)
} else {
q921_setstate(ctrl, Q921_TEI_UNASSIGNED);
pri_schedule_event(ctrl, 0, nt_ptmp_dchannel_up, ctrl);
ctrl = PRI_MASTER(ctrl);
if (!ctrl->subchannel) {
/*
* We do not have any TEI's so 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.
*/
q921_tei_remove(ctrl, Q921_TEI_GROUP);
}
}
} else {
/* PTP mode, no need for TEI management junk */

488
q931.c
View File

@@ -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
*
@@ -4595,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 */
@@ -4606,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 */
@@ -4620,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");
@@ -4646,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);
}
@@ -4946,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)
@@ -4959,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 };
@@ -5461,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;
@@ -5468,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);
@@ -5722,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;
@@ -5871,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;
@@ -6014,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
@@ -6084,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);
@@ -6261,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;
}
@@ -6912,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;
@@ -6934,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;
@@ -6947,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);
@@ -7040,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;
@@ -7597,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;
@@ -7627,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);
@@ -7663,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;
@@ -7676,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;
}
}