Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
271a4f3067 | ||
|
|
64ae283190 | ||
|
|
692697d39b | ||
|
|
9a7715a09d | ||
|
|
a9696d095c | ||
|
|
ea9b8059de | ||
|
|
ee25bdfb5e | ||
|
|
2fd3fff781 | ||
|
|
1b11116f18 | ||
|
|
52c6b7289d | ||
|
|
3cb1f6fbce | ||
|
|
2ab04a7663 | ||
|
|
915d423ffc | ||
|
|
a3a73a30c9 |
120
ChangeLog
120
ChangeLog
@@ -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
113
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)
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
109
q921.c
109
q921.c
@@ -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
488
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
|
||||
*
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user