Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac1c2fc323 | ||
|
|
44b1082a1e | ||
|
|
9a90caa65e | ||
|
|
5414ca525e | ||
|
|
c71499df29 | ||
|
|
2952e95715 | ||
|
|
7da3366cec | ||
|
|
734e922301 | ||
|
|
a9722804c1 | ||
|
|
6b2cc87b30 | ||
|
|
fc96191788 | ||
|
|
5fda3d8c68 | ||
|
|
af8a550ff9 | ||
|
|
a50516c1e4 | ||
|
|
998e6ba598 | ||
|
|
cfac266390 | ||
|
|
13beaacc80 | ||
|
|
84b2560da5 | ||
|
|
28553ff8cb | ||
|
|
1a0927ca23 | ||
|
|
de78c8d37f | ||
|
|
cdb844c16b |
1
.cleancount
Normal file
1
.cleancount
Normal file
@@ -0,0 +1 @@
|
||||
0
|
||||
12
.gitignore
vendored
Normal file
12
.gitignore
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
*.o
|
||||
*.o.d
|
||||
*.lo
|
||||
*.so
|
||||
*.a
|
||||
libpri.so.*
|
||||
pridump
|
||||
pritest
|
||||
rosetest
|
||||
testprilib
|
||||
version.c
|
||||
|
||||
4
.gitreview
Normal file
4
.gitreview
Normal file
@@ -0,0 +1,4 @@
|
||||
[gerrit]
|
||||
host=gerrit.asterisk.org
|
||||
port=29418
|
||||
project=libpri.git
|
||||
1
.lastclean
Normal file
1
.lastclean
Normal file
@@ -0,0 +1 @@
|
||||
0
|
||||
38
libpri-1.5.0-summary.html
Normal file
38
libpri-1.5.0-summary.html
Normal file
@@ -0,0 +1,38 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><title>Release Summary - libpri-1.5.0</title><h1 align="center"><a name="top">Release Summary</a></h1><h3 align="center">libpri-1.5.0</h3><h3 align="center">Date: 2016-03-25</h3><h3 align="center"><asteriskteam@digium.com></h3><hr><h2 align="center">Table of Contents</h2><ol>
|
||||
<li><a href="#summary">Summary</a></li>
|
||||
<li><a href="#contributors">Contributors</a></li>
|
||||
<li><a href="#closed_issues">Closed Issues</a></li>
|
||||
<li><a href="#commits">Other Changes</a></li>
|
||||
<li><a href="#diffstat">Diffstat</a></li>
|
||||
</ol><hr><a name="summary"><h2 align="center">Summary</h2></a><center><a href="#top">[Back to Top]</a></center><p>This release is a point release of an existing major version. The changes included were made to address problems that have been identified in this release series, or are minor, backwards compatible new features or improvements. Users should be able to safely upgrade to this version if this release series is already in use. Users considering upgrading from a previous version are strongly encouraged to review the UPGRADE.txt document as well as the CHANGES document for information about upgrading to this release series.</p><p>The data in this summary reflects changes that have been made since the previous release, libpri-1.4.15.</p><hr><a name="contributors"><h2 align="center">Contributors</h2></a><center><a href="#top">[Back to Top]</a></center><p>This table lists the people who have submitted code, those that have tested patches, as well as those that reported issues on the issue tracker that were resolved in this release. For coders, the number is how many of their patches (of any size) were committed into this release. For testers, the number is the number of times their name was listed as assisting with testing a patch. Finally, for reporters, the number is the number of issues that they reported that were affected by commits that went into this release.</p><table width="100%" border="0">
|
||||
<tr><th width="33%">Coders</th><th width="33%">Testers</th><th width="33%">Reporters</th></tr>
|
||||
<tr valign="top"><td width="33%">8 Richard Mudgett <rmudgett@digium.com><br/>2 Kevin Harwell <kharwell@lunkwill><br/>1 Gerald Schnabel<br/>1 Kevin Harwell <kharwell@digium.com><br/></td><td width="33%"><td width="33%">2 Alexandr Dranchuk <alex.dranchuk@gmail.com><br/>2 Richard Mudgett<br/>2 Alexandr Dranchuk<br/>1 Gerald Schnabel<br/>1 Gerald Schnabel <gs@starface.de><br/>1 Alec Davis <sivad.a@paradise.net.nz><br/>1 James Wilson <james.wilson@integratedvoip.com.au><br/></td></tr>
|
||||
</table><hr><a name="closed_issues"><h2 align="center">Closed Issues</h2></a><center><a href="#top">[Back to Top]</a></center><p>This is a list of all issues from the issue tracker that were closed by changes that went into this release.</p><h3>Bug</h3><h4>Category: General</h4><a href="https://issues.asterisk.org/jira/browse/PRI-180">PRI-180</a>: Incorrect handling of DISCONNECT with Progress Indicator #8<br/>Reported by: Alexandr Dranchuk<ul>
|
||||
<li><a href="https://code.asterisk.org/code/changelog/libpri?cs=2952e95715f26ab239c58d1f0a8213c429514f05">[2952e95715]</a> Richard Mudgett -- q931.c: Fix DISCONNECT Progress Indicator ie handling.</li>
|
||||
<li><a href="https://code.asterisk.org/code/changelog/libpri?cs=7da3366cecf4641d4f27641f3ca5b2bc8dc147a4">[7da3366cec]</a> Richard Mudgett -- q931.c: Substitute PROGRESS for DISCONNECT with progress indicator #8</li>
|
||||
</ul><a href="https://issues.asterisk.org/jira/browse/PRI-74">PRI-74</a>: Unexpected Channel selection<br/>Reported by: James Wilson<ul>
|
||||
<li><a href="https://code.asterisk.org/code/changelog/libpri?cs=fc96191788943877b1ab96113c4804be3ce49753">[fc96191788]</a> Richard Mudgett -- q931.c: Made not recognize ie 0x01 for switches other than 4ESS, 5ESS, NI2, and DMS-100.</li>
|
||||
</ul><a href="https://issues.asterisk.org/jira/browse/PRI-76">PRI-76</a>: [patch] Limit octets received on Called Party Number and Calling Party Number<br/>Reported by: Alec Davis<ul>
|
||||
<li><a href="https://code.asterisk.org/code/changelog/libpri?cs=5fda3d8c68512cf2bdebce3e7cb573eb929eadbd">[5fda3d8c68]</a> Richard Mudgett -- q931.c: Send STATUS messages when receiving messages in the wrong call state.</li>
|
||||
</ul><br><hr><a name="commits"><h2 align="center">Commits Not Associated with an Issue</h2></a><center><a href="#top">[Back to Top]</a></center><p>This is a list of all changes that went into this release that did not reference a JIRA issue.</p><table width="100%" border="1">
|
||||
<tr><th>Revision</th><th>Author</th><th>Summary</th></tr>
|
||||
<tr><td><a href="https://code.asterisk.org/code/changelog/libpri?cs=9a90caa65e131259172fc5167477390ea3237ceb">9a90caa65e</a></td><td>Kevin Harwell</td><td>.version: Update for 1.5.0</td></tr>
|
||||
<tr><td><a href="https://code.asterisk.org/code/changelog/libpri?cs=5414ca525e4c7372e0721060f2259702e3e7a84f">5414ca525e</a></td><td>Kevin Harwell</td><td>.lastclean: Update for 1.5.0</td></tr>
|
||||
<tr><td><a href="https://code.asterisk.org/code/changelog/libpri?cs=c71499df2986c44e25d70840e71bd233d4fe7472">c71499df29</a></td><td>Kevin Harwell</td><td>Adding .cleancount and .gitreview files</td></tr>
|
||||
<tr><td><a href="https://code.asterisk.org/code/changelog/libpri?cs=734e922301bd6154fca4732b2ed693e761772e8b">734e922301</a></td><td>Richard Mudgett</td><td>Add .gitignore</td></tr>
|
||||
<tr><td><a href="https://code.asterisk.org/code/changelog/libpri?cs=a9722804c14b11bdeb483dc2825839a5dc7cd869">a9722804c1</a></td><td>Richard Mudgett</td><td>q931.c: Tighten mandatory ie checks.</td></tr>
|
||||
<tr><td><a href="https://code.asterisk.org/code/changelog/libpri?cs=6b2cc87b301d1871795cc4cd2d15e53f13e88e02">6b2cc87b30</a></td><td>Richard Mudgett</td><td>q931.c: Update ALERTING_NO_PROGRESS conditional code.</td></tr>
|
||||
<tr><td><a href="https://code.asterisk.org/code/changelog/libpri?cs=af8a550ff9566626d1d64a5596434d742b1b0ee5">af8a550ff9</a></td><td>Richard Mudgett</td><td>q921.c: Send DM and DISC frames with only three data octets instead of an extra fourth octet.</td></tr>
|
||||
</table><hr><a name="diffstat"><h2 align="center">Diffstat Results</h2></a><center><a href="#top">[Back to Top]</a></center><p>This is a summary of the changes to the source code that went into this release that was generated using the diffstat utility.</p><pre>ChangeLog | 2056 ---------------------------------------------
|
||||
b/.cleancount | 1
|
||||
b/.gitignore | 12
|
||||
b/.gitreview | 4
|
||||
b/.lastclean | 1
|
||||
b/.version | 2
|
||||
b/pri_internal.h | 7
|
||||
b/pri_q931.h | 3
|
||||
b/q921.c | 4
|
||||
b/q931.c | 383 ++++++--
|
||||
libpri-1.4.15-summary.html | 61 -
|
||||
libpri-1.4.15-summary.txt | 91 -
|
||||
12 files changed, 325 insertions(+), 2300 deletions(-)</pre><br></html>
|
||||
141
libpri-1.5.0-summary.txt
Normal file
141
libpri-1.5.0-summary.txt
Normal file
@@ -0,0 +1,141 @@
|
||||
Release Summary
|
||||
|
||||
libpri-1.5.0
|
||||
|
||||
Date: 2016-03-25
|
||||
|
||||
<asteriskteam@digium.com>
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Table of Contents
|
||||
|
||||
1. Summary
|
||||
2. Contributors
|
||||
3. Closed Issues
|
||||
4. Other Changes
|
||||
5. Diffstat
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Summary
|
||||
|
||||
[Back to Top]
|
||||
|
||||
This release is a point release of an existing major version. The changes
|
||||
included were made to address problems that have been identified in this
|
||||
release series, or are minor, backwards compatible new features or
|
||||
improvements. Users should be able to safely upgrade to this version if
|
||||
this release series is already in use. Users considering upgrading from a
|
||||
previous version are strongly encouraged to review the UPGRADE.txt
|
||||
document as well as the CHANGES document for information about upgrading
|
||||
to this release series.
|
||||
|
||||
The data in this summary reflects changes that have been made since the
|
||||
previous release, libpri-1.4.15.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Contributors
|
||||
|
||||
[Back to Top]
|
||||
|
||||
This table lists the people who have submitted code, those that have
|
||||
tested patches, as well as those that reported issues on the issue tracker
|
||||
that were resolved in this release. For coders, the number is how many of
|
||||
their patches (of any size) were committed into this release. For testers,
|
||||
the number is the number of times their name was listed as assisting with
|
||||
testing a patch. Finally, for reporters, the number is the number of
|
||||
issues that they reported that were affected by commits that went into
|
||||
this release.
|
||||
|
||||
Coders Testers Reporters
|
||||
8 Richard Mudgett 2 Alexandr Dranchuk
|
||||
2 Kevin Harwell 2 Richard Mudgett
|
||||
1 Gerald Schnabel 2 Alexandr Dranchuk
|
||||
1 Kevin Harwell 1 Gerald Schnabel
|
||||
1 Gerald Schnabel
|
||||
1 Alec Davis
|
||||
1 James Wilson
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Closed Issues
|
||||
|
||||
[Back to Top]
|
||||
|
||||
This is a list of all issues from the issue tracker that were closed by
|
||||
changes that went into this release.
|
||||
|
||||
Bug
|
||||
|
||||
Category: General
|
||||
|
||||
PRI-180: Incorrect handling of DISCONNECT with Progress Indicator #8
|
||||
Reported by: Alexandr Dranchuk
|
||||
* [2952e95715] Richard Mudgett -- q931.c: Fix DISCONNECT Progress
|
||||
Indicator ie handling.
|
||||
* [7da3366cec] Richard Mudgett -- q931.c: Substitute PROGRESS for
|
||||
DISCONNECT with progress indicator #8
|
||||
PRI-74: Unexpected Channel selection
|
||||
Reported by: James Wilson
|
||||
* [fc96191788] Richard Mudgett -- q931.c: Made not recognize ie 0x01 for
|
||||
switches other than 4ESS, 5ESS, NI2, and DMS-100.
|
||||
PRI-76: [patch] Limit octets received on Called Party Number and Calling
|
||||
Party Number
|
||||
Reported by: Alec Davis
|
||||
* [5fda3d8c68] Richard Mudgett -- q931.c: Send STATUS messages when
|
||||
receiving messages in the wrong call state.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Commits Not Associated with an Issue
|
||||
|
||||
[Back to Top]
|
||||
|
||||
This is a list of all changes that went into this release that did not
|
||||
reference a JIRA issue.
|
||||
|
||||
+------------------------------------------------------------------------+
|
||||
| Revision | Author | Summary |
|
||||
|------------+-----------------+-----------------------------------------|
|
||||
| 9a90caa65e | Kevin Harwell | .version: Update for 1.5.0 |
|
||||
|------------+-----------------+-----------------------------------------|
|
||||
| 5414ca525e | Kevin Harwell | .lastclean: Update for 1.5.0 |
|
||||
|------------+-----------------+-----------------------------------------|
|
||||
| c71499df29 | Kevin Harwell | Adding .cleancount and .gitreview files |
|
||||
|------------+-----------------+-----------------------------------------|
|
||||
| 734e922301 | Richard Mudgett | Add .gitignore |
|
||||
|------------+-----------------+-----------------------------------------|
|
||||
| a9722804c1 | Richard Mudgett | q931.c: Tighten mandatory ie checks. |
|
||||
|------------+-----------------+-----------------------------------------|
|
||||
| 6b2cc87b30 | Richard Mudgett | q931.c: Update ALERTING_NO_PROGRESS |
|
||||
| | | conditional code. |
|
||||
|------------+-----------------+-----------------------------------------|
|
||||
| | | q921.c: Send DM and DISC frames with |
|
||||
| af8a550ff9 | Richard Mudgett | only three data octets instead of an |
|
||||
| | | extra fourth octet. |
|
||||
+------------------------------------------------------------------------+
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Diffstat Results
|
||||
|
||||
[Back to Top]
|
||||
|
||||
This is a summary of the changes to the source code that went into this
|
||||
release that was generated using the diffstat utility.
|
||||
|
||||
ChangeLog | 2056 ---------------------------------------------
|
||||
b/.cleancount | 1
|
||||
b/.gitignore | 12
|
||||
b/.gitreview | 4
|
||||
b/.lastclean | 1
|
||||
b/.version | 2
|
||||
b/pri_internal.h | 7
|
||||
b/pri_q931.h | 3
|
||||
b/q921.c | 4
|
||||
b/q931.c | 383 ++++++--
|
||||
libpri-1.4.15-summary.html | 61 -
|
||||
libpri-1.4.15-summary.txt | 91 -
|
||||
12 files changed, 325 insertions(+), 2300 deletions(-)
|
||||
66
libpri.h
66
libpri.h
@@ -1213,6 +1213,7 @@ typedef struct pri_event_setup_ack {
|
||||
int channel;
|
||||
q931_call *call;
|
||||
struct pri_subcommands *subcmds;
|
||||
int progressmask;
|
||||
} pri_event_setup_ack;
|
||||
|
||||
typedef struct pri_event_notify {
|
||||
@@ -1408,8 +1409,17 @@ const char *pri_facility_error2str(int facility_error_code);
|
||||
*/
|
||||
const char *pri_facility_reject2str(int facility_reject_code);
|
||||
|
||||
/* Acknowledge a call and place it on the given channel. Set info to non-zero if there
|
||||
is in-band data available on the channel */
|
||||
/*!
|
||||
* \brief Send the ALERTING message.
|
||||
*
|
||||
* \param pri D channel controller.
|
||||
* \param call Q.931 call leg.
|
||||
* \param channel Encoded channel id to use. If zero do not change channel id.
|
||||
* \param info Nonzero to include a progress ie indicating inband audio available (ie ringback).
|
||||
*
|
||||
* \retval 0 on success.
|
||||
* \retval -1 on error.
|
||||
*/
|
||||
int pri_acknowledge(struct pri *pri, q931_call *call, int channel, int info);
|
||||
|
||||
/* Send a digit in overlap mode */
|
||||
@@ -1419,12 +1429,44 @@ int pri_information(struct pri *pri, q931_call *call, char digit);
|
||||
/* Send a keypad facility string of digits */
|
||||
int pri_keypad_facility(struct pri *pri, q931_call *call, const char *digits);
|
||||
|
||||
/* Answer the incomplete(call without called number) call on the given channel.
|
||||
Set non-isdn to non-zero if you are not connecting to ISDN equipment */
|
||||
/*!
|
||||
* \brief Send the SETUP_ACKNOWLEDGE message.
|
||||
*
|
||||
* \param pri D channel controller.
|
||||
* \param call Q.931 call leg.
|
||||
* \param channel Encoded channel id to use. If zero do not change channel id.
|
||||
* \param nonisdn Nonzero to include a progress ie indicating non-end-to-end-ISDN.
|
||||
*
|
||||
* \retval 0 on success.
|
||||
* \retval -1 on error.
|
||||
*/
|
||||
int pri_need_more_info(struct pri *pri, q931_call *call, int channel, int nonisdn);
|
||||
|
||||
/* Answer(CONNECT) the call on the given channel.
|
||||
Set non-isdn to non-zero if you are not connecting to ISDN equipment */
|
||||
/*!
|
||||
* \brief Send the SETUP_ACKNOWLEDGE message.
|
||||
*
|
||||
* \param ctrl D channel controller.
|
||||
* \param call Q.931 call leg.
|
||||
* \param channel Encoded channel id to use. If zero do not change channel id.
|
||||
* \param nonisdn Nonzero to include a progress ie indicating non-end-to-end-ISDN.
|
||||
* \param inband Nonzero to include a progress ie indicating inband audio available (ie dialtone).
|
||||
*
|
||||
* \retval 0 on success.
|
||||
* \retval -1 on error.
|
||||
*/
|
||||
int pri_setup_ack(struct pri *ctrl, q931_call *call, int channel, int nonisdn, int inband);
|
||||
|
||||
/*!
|
||||
* \brief Send the CONNECT message.
|
||||
*
|
||||
* \param pri D channel controller.
|
||||
* \param call Q.931 call leg.
|
||||
* \param channel Encoded channel id to use. If zero do not change channel id.
|
||||
* \param nonisdn Nonzero to include a progress ie indicating non-end-to-end-ISDN.
|
||||
*
|
||||
* \retval 0 on success.
|
||||
* \retval -1 on error.
|
||||
*/
|
||||
int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn);
|
||||
|
||||
/*!
|
||||
@@ -1692,7 +1734,17 @@ int pri_progress(struct pri *pri, q931_call *c, int channel, int info);
|
||||
int pri_progress_with_cause(struct pri *pri, q931_call *c, int channel, int info, int cause);
|
||||
|
||||
#define PRI_PROCEEDING_FULL
|
||||
/* Send call proceeding */
|
||||
/*!
|
||||
* \brief Send the PROCEEDING message.
|
||||
*
|
||||
* \param pri D channel controller.
|
||||
* \param c Q.931 call leg.
|
||||
* \param channel Encoded channel id to use. If zero do not change channel id.
|
||||
* \param info Nonzero to include a progress ie indicating inband audio available.
|
||||
*
|
||||
* \retval 0 on success.
|
||||
* \retval -1 on error.
|
||||
*/
|
||||
int pri_proceeding(struct pri *pri, q931_call *c, int channel, int info);
|
||||
|
||||
/* Enable inband progress when a DISCONNECT is received */
|
||||
|
||||
12
pri.c
12
pri.c
@@ -176,7 +176,7 @@ static void pri_default_timers(struct pri *ctrl, int switchtype)
|
||||
|
||||
ctrl->timers[PRI_TIMER_T200] = 1000; /* Time between SABME's */
|
||||
ctrl->timers[PRI_TIMER_T201] = ctrl->timers[PRI_TIMER_T200];/* Time between TEI Identity Checks (Default same as T200) */
|
||||
ctrl->timers[PRI_TIMER_T202] = 10 * 1000; /* Min time between transmission of TEI Identity request messages */
|
||||
ctrl->timers[PRI_TIMER_T202] = 2 * 1000; /* Min time between transmission of TEI Identity request messages */
|
||||
ctrl->timers[PRI_TIMER_T203] = 10 * 1000; /* Max time without exchanging packets */
|
||||
|
||||
ctrl->timers[PRI_TIMER_T303] = 4 * 1000; /* Length between SETUP retransmissions and timeout */
|
||||
@@ -939,7 +939,15 @@ int pri_need_more_info(struct pri *pri, q931_call *call, int channel, int nonisd
|
||||
if (!pri || !pri_is_call_valid(pri, call)) {
|
||||
return -1;
|
||||
}
|
||||
return q931_setup_ack(pri, call, channel, nonisdn);
|
||||
return q931_setup_ack(pri, call, channel, nonisdn, 0);
|
||||
}
|
||||
|
||||
int pri_setup_ack(struct pri *ctrl, q931_call *call, int channel, int nonisdn, int inband)
|
||||
{
|
||||
if (!ctrl || !pri_is_call_valid(ctrl, call)) {
|
||||
return -1;
|
||||
}
|
||||
return q931_setup_ack(ctrl, call, channel, nonisdn, inband);
|
||||
}
|
||||
|
||||
int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn)
|
||||
|
||||
@@ -647,10 +647,13 @@ struct q931_call {
|
||||
unsigned char char_set;
|
||||
} display;
|
||||
|
||||
/* AOC charge requesting on Setup */
|
||||
/*! AOC charge requesting on Setup */
|
||||
int aoc_charging_request;
|
||||
|
||||
unsigned int slotmap_size:1;/* TRUE if the slotmap is E1 (32 bits). */
|
||||
/*! TRUE if the slotmap is E1 (32 bits). */
|
||||
unsigned int slotmap_size:1;
|
||||
/*! TRUE if need to see the channel id ie in first response to SETUP. */
|
||||
unsigned int channel_id_ie_mandatory:1;
|
||||
|
||||
/*! Control the RESTART reception to the upper layer. */
|
||||
struct {
|
||||
|
||||
@@ -138,9 +138,6 @@ typedef struct q931_ie {
|
||||
#define SERVICE_CHANGE_STATUS_REQCONTINUITYCHECK 3 /* not supported */
|
||||
#define SERVICE_CHANGE_STATUS_SHUTDOWN 4 /* not supported */
|
||||
|
||||
/* Special codeset 0 IE */
|
||||
#define NATIONAL_CHANGE_STATUS 0x1
|
||||
|
||||
/* Q.931 / National ISDN Information Elements */
|
||||
#define Q931_LOCKING_SHIFT 0x90
|
||||
#define Q931_NON_LOCKING_SHIFT 0x98
|
||||
@@ -468,7 +465,7 @@ extern int q931_notify(struct pri *pri, q931_call *call, int channel, int info);
|
||||
|
||||
extern int q931_call_proceeding(struct pri *pri, q931_call *call, int channel, int info);
|
||||
|
||||
extern int q931_setup_ack(struct pri *pri, q931_call *call, int channel, int nonisdn);
|
||||
extern int q931_setup_ack(struct pri *ctrl, q931_call *c, int channel, int nonisdn, int inband);
|
||||
|
||||
extern int q931_information(struct pri *pri, q931_call *call, char digit);
|
||||
|
||||
|
||||
@@ -68,7 +68,10 @@ static void do_channel(int fd)
|
||||
int i=0;
|
||||
|
||||
while ((res = read(fd, buf, READ_SIZE)) > 0 && (i++ < 1000)) {
|
||||
write(fd, buf, res);
|
||||
if (write(fd, buf, res) == -1) {
|
||||
fprintf(stderr, "--!! Failed write: %d\n", errno);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
214
q921.c
214
q921.c
@@ -45,13 +45,19 @@
|
||||
*/
|
||||
//#define RANDOM_DROPS 1
|
||||
|
||||
#define Q921_INIT(link, hf) do { \
|
||||
memset(&(hf),0,sizeof(hf)); \
|
||||
(hf).h.sapi = (link)->sapi; \
|
||||
(hf).h.ea1 = 0; \
|
||||
(hf).h.ea2 = 1; \
|
||||
(hf).h.tei = (link)->tei; \
|
||||
} while (0)
|
||||
#define Q921_INIT(fr, l_sapi, l_tei) \
|
||||
do { \
|
||||
(fr)->h.sapi = l_sapi; \
|
||||
(fr)->h.ea1 = 0; \
|
||||
(fr)->h.ea2 = 1; \
|
||||
(fr)->h.tei = l_tei; \
|
||||
} while (0)
|
||||
|
||||
#define Q921_CLEAR_INIT(fr, l_sapi, l_tei) \
|
||||
do { \
|
||||
memset((fr), 0, sizeof(*(fr))); \
|
||||
Q921_INIT((fr), (l_sapi), (l_tei)); \
|
||||
} while (0)
|
||||
|
||||
static void q921_dump_pri(struct q921_link *link, char direction_tag);
|
||||
static void q921_establish_data_link(struct q921_link *link);
|
||||
@@ -196,17 +202,14 @@ static int q921_transmit(struct pri *ctrl, q921_h *h, int len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void q921_send_tei(struct pri *ctrl, enum q921_tei_identity message, int ri, int ai, int iscommand)
|
||||
static void q921_mdl_send(struct pri *ctrl, enum q921_tei_identity message, int ri, int ai, int iscommand)
|
||||
{
|
||||
q921_u *f;
|
||||
struct q921_link *link;
|
||||
|
||||
link = &ctrl->link;
|
||||
|
||||
if (!(f = calloc(1, sizeof(*f) + 5)))
|
||||
return;
|
||||
|
||||
Q921_INIT(link, *f);
|
||||
Q921_INIT(f, Q921_SAPI_LAYER2_MANAGEMENT, Q921_TEI_GROUP);
|
||||
f->h.c_r = (ctrl->localtype == PRI_NETWORK) ? iscommand : !iscommand;
|
||||
f->ft = Q921_FRAMETYPE_U;
|
||||
f->data[0] = 0x0f; /* Management entity */
|
||||
@@ -216,7 +219,7 @@ static void q921_send_tei(struct pri *ctrl, enum q921_tei_identity message, int
|
||||
f->data[4] = (ai << 1) | 1;
|
||||
if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
|
||||
pri_message(ctrl,
|
||||
"Sending TEI management message %d(%s), TEI=%d\n",
|
||||
"Sending MDL message: %d(%s), TEI=%d\n",
|
||||
message, q921_tei_mgmt2str(message), ai);
|
||||
}
|
||||
q921_transmit(ctrl, (q921_h *)f, 8);
|
||||
@@ -265,7 +268,7 @@ static void t202_expire(void *vlink)
|
||||
|
||||
/* Send TEI request */
|
||||
link->ri = random() % 65535;
|
||||
q921_send_tei(ctrl, Q921_TEI_IDENTITY_REQUEST, link->ri, Q921_TEI_GROUP, 1);
|
||||
q921_mdl_send(ctrl, Q921_TEI_IDENTITY_REQUEST, link->ri, Q921_TEI_GROUP, 1);
|
||||
}
|
||||
|
||||
static void q921_tei_request(struct q921_link *link)
|
||||
@@ -280,8 +283,8 @@ 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);
|
||||
q921_mdl_send(ctrl, Q921_TEI_IDENTITY_REMOVE, 0, tei, 1);
|
||||
q921_mdl_send(ctrl, Q921_TEI_IDENTITY_REMOVE, 0, tei, 1);
|
||||
}
|
||||
|
||||
static void q921_send_dm(struct q921_link *link, int fbit)
|
||||
@@ -291,7 +294,7 @@ static void q921_send_dm(struct q921_link *link, int fbit)
|
||||
|
||||
ctrl = link->ctrl;
|
||||
|
||||
Q921_INIT(link, h);
|
||||
Q921_CLEAR_INIT(&h, link->sapi, link->tei);
|
||||
h.u.m3 = 0; /* M3 = 0 */
|
||||
h.u.m2 = 3; /* M2 = 3 */
|
||||
h.u.p_f = fbit; /* Final set appropriately */
|
||||
@@ -310,7 +313,7 @@ static void q921_send_dm(struct q921_link *link, int fbit)
|
||||
if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
|
||||
pri_message(ctrl, "TEI=%d Sending DM\n", link->tei);
|
||||
}
|
||||
q921_transmit(ctrl, &h, 4);
|
||||
q921_transmit(ctrl, &h, 3);
|
||||
}
|
||||
|
||||
static void q921_send_disc(struct q921_link *link, int pbit)
|
||||
@@ -320,7 +323,7 @@ static void q921_send_disc(struct q921_link *link, int pbit)
|
||||
|
||||
ctrl = link->ctrl;
|
||||
|
||||
Q921_INIT(link, h);
|
||||
Q921_CLEAR_INIT(&h, link->sapi, link->tei);
|
||||
h.u.m3 = 2; /* M3 = 2 */
|
||||
h.u.m2 = 0; /* M2 = 0 */
|
||||
h.u.p_f = pbit; /* Poll set appropriately */
|
||||
@@ -339,7 +342,7 @@ static void q921_send_disc(struct q921_link *link, int pbit)
|
||||
if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
|
||||
pri_message(ctrl, "TEI=%d Sending DISC\n", link->tei);
|
||||
}
|
||||
q921_transmit(ctrl, &h, 4);
|
||||
q921_transmit(ctrl, &h, 3);
|
||||
}
|
||||
|
||||
static void q921_send_ua(struct q921_link *link, int fbit)
|
||||
@@ -349,7 +352,7 @@ static void q921_send_ua(struct q921_link *link, int fbit)
|
||||
|
||||
ctrl = link->ctrl;
|
||||
|
||||
Q921_INIT(link, h);
|
||||
Q921_CLEAR_INIT(&h, link->sapi, link->tei);
|
||||
h.u.m3 = 3; /* M3 = 3 */
|
||||
h.u.m2 = 0; /* M2 = 0 */
|
||||
h.u.p_f = fbit; /* Final set appropriately */
|
||||
@@ -378,7 +381,7 @@ static void q921_send_sabme(struct q921_link *link)
|
||||
|
||||
ctrl = link->ctrl;
|
||||
|
||||
Q921_INIT(link, h);
|
||||
Q921_CLEAR_INIT(&h, link->sapi, link->tei);
|
||||
h.u.m3 = 3; /* M3 = 3 */
|
||||
h.u.m2 = 3; /* M2 = 3 */
|
||||
h.u.p_f = 1; /* Poll bit set */
|
||||
@@ -557,7 +560,7 @@ static void kick_start_link(struct q921_link *link)
|
||||
break;
|
||||
case Q921_ASSIGN_AWAITING_TEI:
|
||||
if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
|
||||
pri_message(ctrl, "Kick starting link when get TEI.\n");
|
||||
pri_message(ctrl, "Kick starting link when awaiting TEI.\n");
|
||||
}
|
||||
q921_setstate(link, Q921_ESTABLISH_AWAITING_TEI);
|
||||
break;
|
||||
@@ -586,6 +589,8 @@ static void restart_timer_expire(void *vlink)
|
||||
link->restart_timer = 0;
|
||||
|
||||
switch (link->state) {
|
||||
case Q921_TEI_UNASSIGNED:
|
||||
case Q921_ASSIGN_AWAITING_TEI:
|
||||
case Q921_TEI_ASSIGNED:
|
||||
/* Try to bring layer 2 up. */
|
||||
kick_start_link(link);
|
||||
@@ -807,7 +812,7 @@ static void q921_reject(struct q921_link *link, int pf)
|
||||
|
||||
ctrl = link->ctrl;
|
||||
|
||||
Q921_INIT(link, h);
|
||||
Q921_CLEAR_INIT(&h, link->sapi, link->tei);
|
||||
h.s.x0 = 0; /* Always 0 */
|
||||
h.s.ss = 2; /* Reject */
|
||||
h.s.ft = 1; /* Frametype (01) */
|
||||
@@ -837,7 +842,7 @@ static void q921_rr(struct q921_link *link, int pbit, int cmd)
|
||||
|
||||
ctrl = link->ctrl;
|
||||
|
||||
Q921_INIT(link, h);
|
||||
Q921_CLEAR_INIT(&h, link->sapi, link->tei);
|
||||
h.s.x0 = 0; /* Always 0 */
|
||||
h.s.ss = 0; /* Receive Ready */
|
||||
h.s.ft = 1; /* Frametype (01) */
|
||||
@@ -1064,7 +1069,7 @@ int q921_transmit_iframe(struct q921_link *link, void *buf, int len, int cr)
|
||||
|
||||
f = calloc(1, sizeof(struct q921_frame) + len + 2);
|
||||
if (f) {
|
||||
Q921_INIT(link, f->h);
|
||||
Q921_INIT(&f->h, link->sapi, link->tei);
|
||||
switch (ctrl->localtype) {
|
||||
case PRI_NETWORK:
|
||||
if (cr)
|
||||
@@ -1394,12 +1399,6 @@ static void t201_expire(void *vctrl)
|
||||
|
||||
ctrl = vctrl;
|
||||
|
||||
if (!ctrl->link.next) {
|
||||
/* No TEI links remain. */
|
||||
ctrl->t201_timer = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Start the TEI check timer. */
|
||||
ctrl->t201_timer =
|
||||
pri_schedule_event(ctrl, ctrl->timers[PRI_TIMER_T201], t201_expire, ctrl);
|
||||
@@ -1460,7 +1459,7 @@ static void t201_expire(void *vctrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
q921_send_tei(ctrl, Q921_TEI_IDENTITY_CHECK_REQUEST, 0, Q921_TEI_GROUP, 1);
|
||||
q921_mdl_send(ctrl, Q921_TEI_IDENTITY_CHECK_REQUEST, 0, Q921_TEI_GROUP, 1);
|
||||
}
|
||||
|
||||
static void q921_tei_check(struct pri *ctrl)
|
||||
@@ -1473,7 +1472,19 @@ static void q921_tei_check(struct pri *ctrl)
|
||||
t201_expire(ctrl);
|
||||
}
|
||||
|
||||
static pri_event *q921_receive_MDL(struct pri *ctrl, q921_u *h, int len)
|
||||
static void q921_mdl_ignore(struct pri *ctrl, q921_u *h, const char *reason)
|
||||
{
|
||||
if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
|
||||
/*
|
||||
* Send out this message in debug modes since it is possible the
|
||||
* user has misconfigured their link for the wrong mode.
|
||||
*/
|
||||
pri_message(ctrl, "Ignoring MDL message: %d(%s) %s\n",
|
||||
h->data[3], q921_tei_mgmt2str(h->data[3]), reason);
|
||||
}
|
||||
}
|
||||
|
||||
static pri_event *q921_mdl_receive(struct pri *ctrl, q921_u *h, int len)
|
||||
{
|
||||
int ri;
|
||||
struct q921_link *sub;
|
||||
@@ -1483,32 +1494,13 @@ static pri_event *q921_receive_MDL(struct pri *ctrl, q921_u *h, int len)
|
||||
int count;
|
||||
int tei;
|
||||
|
||||
if (!BRI_NT_PTMP(ctrl) && !BRI_TE_PTMP(ctrl)) {
|
||||
/*
|
||||
* Some telco switches send out MDL messages even though they
|
||||
* are configured for PTP. Usually they are checking for
|
||||
* assigned TEI's.
|
||||
*/
|
||||
if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
|
||||
/*
|
||||
* Send out this message in debug modes since it is possible the
|
||||
* user has misconfigured their link for the wrong mode.
|
||||
*/
|
||||
pri_message(ctrl, "Not configured for PTMP. Ignoring MDL message: %d(%s)\n",
|
||||
h->data[3], q921_tei_mgmt2str(h->data[3]));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
|
||||
pri_message(ctrl, "Received MDL message\n");
|
||||
}
|
||||
if (len <= &h->data[0] - (u_int8_t *) h) {
|
||||
pri_error(ctrl, "Received short frame\n");
|
||||
pri_error(ctrl, "Received short MDL frame\n");
|
||||
return NULL;
|
||||
}
|
||||
if (h->data[0] != 0x0f) {
|
||||
pri_error(ctrl, "Received MDL with unsupported management entity %02x\n", h->data[0]);
|
||||
pri_error(ctrl, "Received MDL with unsupported management entity %02x\n",
|
||||
h->data[0]);
|
||||
return NULL;
|
||||
}
|
||||
if (len <= &h->data[4] - (u_int8_t *) h) {
|
||||
@@ -1517,8 +1509,20 @@ static pri_event *q921_receive_MDL(struct pri *ctrl, q921_u *h, int len)
|
||||
}
|
||||
if (h->data[3] != Q921_TEI_IDENTITY_CHECK_RESPONSE
|
||||
&& !(h->data[4] & 0x01)) {
|
||||
pri_error(ctrl, "Received %d(%s) with Ai E bit not set.\n", h->data[3],
|
||||
q921_tei_mgmt2str(h->data[3]));
|
||||
pri_error(ctrl, "Received MDL message: %d(%s) with Ai E bit not set.\n",
|
||||
h->data[3], q921_tei_mgmt2str(h->data[3]));
|
||||
return NULL;
|
||||
}
|
||||
if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
|
||||
pri_message(ctrl, "Received MDL message: %d(%s)\n",
|
||||
h->data[3], q921_tei_mgmt2str(h->data[3]));
|
||||
}
|
||||
if (PTP_MODE(ctrl) && NT_MODE(ctrl)) {
|
||||
/*
|
||||
* We are not managing automatic TEI's in this mode so we can
|
||||
* ignore MDL messages from the CPE.
|
||||
*/
|
||||
q921_mdl_ignore(ctrl, h, "We are in NT-PTP mode.");
|
||||
return NULL;
|
||||
}
|
||||
ri = (h->data[1] << 8) | h->data[2];
|
||||
@@ -1527,13 +1531,14 @@ static pri_event *q921_receive_MDL(struct pri *ctrl, q921_u *h, int len)
|
||||
switch (h->data[3]) {
|
||||
case Q921_TEI_IDENTITY_REQUEST:
|
||||
if (!BRI_NT_PTMP(ctrl)) {
|
||||
q921_mdl_ignore(ctrl, h, "We are not in NT-PTMP mode.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (tei != Q921_TEI_GROUP) {
|
||||
pri_error(ctrl, "Received %s with invalid TEI %d\n",
|
||||
q921_tei_mgmt2str(Q921_TEI_IDENTITY_REQUEST), tei);
|
||||
q921_send_tei(ctrl, Q921_TEI_IDENTITY_DENIED, ri, tei, 1);
|
||||
q921_mdl_send(ctrl, Q921_TEI_IDENTITY_DENIED, ri, tei, 1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1548,7 +1553,7 @@ static pri_event *q921_receive_MDL(struct pri *ctrl, q921_u *h, int len)
|
||||
break;
|
||||
}
|
||||
pri_error(ctrl, "TEI pool exhausted. Reclaiming dead TEIs.\n");
|
||||
q921_send_tei(ctrl, Q921_TEI_IDENTITY_DENIED, ri, Q921_TEI_GROUP, 1);
|
||||
q921_mdl_send(ctrl, Q921_TEI_IDENTITY_DENIED, ri, Q921_TEI_GROUP, 1);
|
||||
q921_tei_check(ctrl);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1565,7 +1570,7 @@ static pri_event *q921_receive_MDL(struct pri *ctrl, q921_u *h, int len)
|
||||
}
|
||||
sub->next = link;
|
||||
q921_setstate(link, Q921_TEI_ASSIGNED);
|
||||
q921_send_tei(ctrl, Q921_TEI_IDENTITY_ASSIGNED, ri, tei, 1);
|
||||
q921_mdl_send(ctrl, Q921_TEI_IDENTITY_ASSIGNED, ri, tei, 1);
|
||||
|
||||
count = 0;
|
||||
for (sub = ctrl->link.next; sub; sub = sub->next) {
|
||||
@@ -1593,6 +1598,7 @@ static pri_event *q921_receive_MDL(struct pri *ctrl, q921_u *h, int len)
|
||||
break;
|
||||
case Q921_TEI_IDENTITY_CHECK_RESPONSE:
|
||||
if (!BRI_NT_PTMP(ctrl)) {
|
||||
/* Silently ignore the message since we never asked for the check. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1640,6 +1646,7 @@ static pri_event *q921_receive_MDL(struct pri *ctrl, q921_u *h, int len)
|
||||
break;
|
||||
case Q921_TEI_IDENTITY_VERIFY:
|
||||
if (!BRI_NT_PTMP(ctrl)) {
|
||||
q921_mdl_ignore(ctrl, h, "We are not in NT-PTMP mode.");
|
||||
return NULL;
|
||||
}
|
||||
if (tei == Q921_TEI_GROUP) {
|
||||
@@ -1650,11 +1657,20 @@ static pri_event *q921_receive_MDL(struct pri *ctrl, q921_u *h, int len)
|
||||
q921_tei_check(ctrl);
|
||||
break;
|
||||
case Q921_TEI_IDENTITY_ASSIGNED:
|
||||
if (NT_MODE(ctrl)) {
|
||||
/* We should not be receiving this message. */
|
||||
q921_mdl_ignore(ctrl, h, "We are the network.");
|
||||
return NULL;
|
||||
}
|
||||
if (!BRI_TE_PTMP(ctrl)) {
|
||||
/*
|
||||
* Silently ignore the message. It must not be for us
|
||||
* since we will never ask for one.
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Assuming we're operating on the specific TEI link here */
|
||||
/* We're operating on the specific TEI link here */
|
||||
link = ctrl->link.next;
|
||||
|
||||
switch (link->state) {
|
||||
@@ -1724,29 +1740,52 @@ static pri_event *q921_receive_MDL(struct pri *ctrl, q921_u *h, int len)
|
||||
}
|
||||
break;
|
||||
case Q921_TEI_IDENTITY_CHECK_REQUEST:
|
||||
if (!BRI_TE_PTMP(ctrl)) {
|
||||
if (NT_MODE(ctrl)) {
|
||||
/* We should not be receiving this message. */
|
||||
q921_mdl_ignore(ctrl, h, "We are the network.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Assuming we're operating on the specific TEI link here */
|
||||
link = ctrl->link.next;
|
||||
if (PTP_MODE(ctrl)) {
|
||||
/*
|
||||
* Some telco switches/devices get very unhappy if we don't
|
||||
* respond to the TEI check request with our permanently
|
||||
* assigned TEI.
|
||||
*/
|
||||
link = &ctrl->link;
|
||||
} else if (BRI_TE_PTMP(ctrl)) {
|
||||
/* We're operating on the specific TEI link here */
|
||||
link = ctrl->link.next;
|
||||
|
||||
if (link->state < Q921_TEI_ASSIGNED) {
|
||||
/* We do not have a TEI. */
|
||||
if (link->state < Q921_TEI_ASSIGNED) {
|
||||
/* We do not have a TEI. */
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
/* Should never get here. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* If it's addressed to the group TEI or to our TEI specifically, we respond */
|
||||
if (tei == Q921_TEI_GROUP || tei == link->tei) {
|
||||
q921_send_tei(ctrl, Q921_TEI_IDENTITY_CHECK_RESPONSE, random() % 65535, link->tei, 1);
|
||||
q921_mdl_send(ctrl, Q921_TEI_IDENTITY_CHECK_RESPONSE, random() % 65535, link->tei, 1);
|
||||
}
|
||||
break;
|
||||
case Q921_TEI_IDENTITY_REMOVE:
|
||||
if (NT_MODE(ctrl)) {
|
||||
/* We should not be receiving this message. */
|
||||
q921_mdl_ignore(ctrl, h, "We are the network.");
|
||||
return NULL;
|
||||
}
|
||||
if (!BRI_TE_PTMP(ctrl)) {
|
||||
/*
|
||||
* Silently ignore the message. If we are TE-PTP our
|
||||
* TEI is permanently assigned and cannot be removed.
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Assuming we're operating on the specific TEI link here */
|
||||
/* We're operating on the specific TEI link here */
|
||||
link = ctrl->link.next;
|
||||
|
||||
if (link->state < Q921_TEI_ASSIGNED) {
|
||||
@@ -1911,7 +1950,9 @@ static void q921_mdl_remove(struct q921_link *link)
|
||||
|
||||
switch (link->state) {
|
||||
case Q921_TEI_ASSIGNED:
|
||||
restart_timer_stop(link);
|
||||
if (mdl_free_me) {
|
||||
restart_timer_stop(link);
|
||||
}
|
||||
/* XXX: deviation! Since we don't have a UI queue, we just discard our I-queue */
|
||||
q921_discard_iqueue(link);
|
||||
q921_setstate(link, Q921_TEI_UNASSIGNED);
|
||||
@@ -2987,27 +3028,32 @@ static pri_event *__q921_receive_qualified(struct q921_link *link, q921_h *h, in
|
||||
|
||||
static pri_event *q921_handle_unmatched_frame(struct pri *ctrl, q921_h *h, int len)
|
||||
{
|
||||
if (h->h.tei < 64) {
|
||||
pri_error(ctrl, "Do not support manual TEI range. Discarding\n");
|
||||
if (!BRI_NT_PTMP(ctrl)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (h->h.tei < Q921_TEI_AUTO_FIRST) {
|
||||
if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
|
||||
pri_message(ctrl, "Manual TEI range is not supported in NT-PTMP mode. Discarding\n");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (h->h.sapi != Q921_SAPI_CALL_CTRL) {
|
||||
pri_error(ctrl, "Message with SAPI other than CALL CTRL is discarded\n");
|
||||
if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
|
||||
pri_message(ctrl, "Message with SAPI other than CALL CTRL is discarded\n");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* If we're NT-PTMP, this means an unrecognized TEI that we'll kill */
|
||||
if (BRI_NT_PTMP(ctrl)) {
|
||||
if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
|
||||
pri_message(ctrl,
|
||||
"Could not find a layer 2 link for received frame with SAPI/TEI of %d/%d.\n",
|
||||
h->h.sapi, h->h.tei);
|
||||
pri_message(ctrl, "Sending TEI release, in order to re-establish TEI state\n");
|
||||
}
|
||||
|
||||
q921_tei_remove(ctrl, h->h.tei);
|
||||
/* This means an unrecognized TEI that we'll kill */
|
||||
if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
|
||||
pri_message(ctrl,
|
||||
"Could not find a layer 2 link for received frame with SAPI/TEI of %d/%d.\n",
|
||||
h->h.sapi, h->h.tei);
|
||||
pri_message(ctrl, "Sending TEI release, in order to re-establish TEI state\n");
|
||||
}
|
||||
q921_tei_remove(ctrl, h->h.tei);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -3031,7 +3077,7 @@ static pri_event *__q921_receive(struct pri *ctrl, q921_h *h, int len)
|
||||
}
|
||||
|
||||
if (h->h.sapi == Q921_SAPI_LAYER2_MANAGEMENT) {
|
||||
return q921_receive_MDL(ctrl, &h->u, len);
|
||||
return q921_mdl_receive(ctrl, &h->u, len);
|
||||
}
|
||||
|
||||
if (h->h.tei == Q921_TEI_GROUP && h->h.sapi != Q921_SAPI_CALL_CTRL) {
|
||||
|
||||
500
q931.c
500
q931.c
@@ -40,6 +40,12 @@
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
|
||||
enum mandatory_ie_status {
|
||||
MAND_STATUS_OK,
|
||||
MAND_STATUS_CONTENT_ERROR,
|
||||
MAND_STATUS_MISSING,
|
||||
};
|
||||
|
||||
#define MAX_MAND_IES 10
|
||||
|
||||
struct msgtype {
|
||||
@@ -50,13 +56,27 @@ struct msgtype {
|
||||
|
||||
static struct msgtype msgs[] = {
|
||||
/* Call establishment messages */
|
||||
{ Q931_ALERTING, "ALERTING" },
|
||||
{ Q931_CALL_PROCEEDING, "CALL PROCEEDING" },
|
||||
{ Q931_CONNECT, "CONNECT" },
|
||||
{ Q931_ALERTING, "ALERTING", { Q931_CHANNEL_IDENT } },
|
||||
{ Q931_CALL_PROCEEDING, "CALL PROCEEDING", { Q931_CHANNEL_IDENT } },
|
||||
{ Q931_CONNECT, "CONNECT", { Q931_CHANNEL_IDENT } },
|
||||
{ Q931_CONNECT_ACKNOWLEDGE, "CONNECT ACKNOWLEDGE" },
|
||||
/*
|
||||
* Very early in libpri SVN history (SVN -r154) a change was explicitly
|
||||
* made to not care about a missing Progress Indicator ie. There is no
|
||||
* explanation in the commit message why this was done even though
|
||||
* Q.931 and ECMA-143 clearly show that the ie is mandatory for a
|
||||
* PROGRESS message.
|
||||
*
|
||||
* Hazzarding a guess, I think it was because of the
|
||||
* ALERTING_NO_PROGRESS support for Mitel switches. (SVN -r44)
|
||||
*/
|
||||
#ifdef ALERTING_NO_PROGRESS
|
||||
{ Q931_PROGRESS, "PROGRESS" },
|
||||
#else
|
||||
{ Q931_PROGRESS, "PROGRESS", { Q931_PROGRESS_INDICATOR } },
|
||||
#endif
|
||||
{ Q931_SETUP, "SETUP", { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT } },
|
||||
{ Q931_SETUP_ACKNOWLEDGE, "SETUP ACKNOWLEDGE" },
|
||||
{ Q931_SETUP_ACKNOWLEDGE, "SETUP ACKNOWLEDGE", { Q931_CHANNEL_IDENT } },
|
||||
|
||||
/* Call disestablishment messages */
|
||||
{ Q931_DISCONNECT, "DISCONNECT", { Q931_CAUSE } },
|
||||
@@ -93,7 +113,7 @@ static struct msgtype msgs[] = {
|
||||
{ Q931_ANY_MESSAGE, "ANY MESSAGE" },
|
||||
};
|
||||
|
||||
static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct q931_call *c, int missingmand);
|
||||
static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct q931_call *c, enum mandatory_ie_status mand_status);
|
||||
static void nt_ptmp_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct q931_call *c, int *allow_event, int *allow_posthandle);
|
||||
|
||||
struct msgtype att_maintenance_msgs[] = {
|
||||
@@ -1258,6 +1278,14 @@ static int receive_channel_id(int full_ie, struct pri *ctrl, q931_call *call, in
|
||||
int pos = 0;
|
||||
int need_extended_channel_octets;/*!< TRUE if octets 3.2 and 3.3 need to be present. */
|
||||
|
||||
call->channel_id_ie_mandatory = 0;
|
||||
|
||||
if (ie->len < 1) {
|
||||
/* Must have at least one payload octet. */
|
||||
pri_error(ctrl, "!! Channel Identification ie too short\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
call->restart.count = 0;
|
||||
|
||||
if (ie->data[0] & 0x08) {
|
||||
@@ -1308,10 +1336,24 @@ static int receive_channel_id(int full_ie, struct pri *ctrl, q931_call *call, in
|
||||
|
||||
pos++;
|
||||
if (ie->data[0] & 0x40) {
|
||||
/* DS1 specified -- stop here */
|
||||
call->ds1no = ie->data[1] & 0x7f;
|
||||
/* Explicitly defined DS1 (One or more 3.1 octets expected) */
|
||||
if (ctrl->switchtype == PRI_SWITCH_QSIG) {
|
||||
pri_error(ctrl, "!! Q.SIG does not support Channel Identification octet 3.1\n");
|
||||
return -1;
|
||||
}
|
||||
if (ie->len <= pos) {
|
||||
pri_error(ctrl, "!! Missing expected Channel Identification octet 3.1\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Extract explicit DS1 reference. */
|
||||
call->ds1no = ie->data[pos] & 0x7f;
|
||||
call->ds1explicit = 1;
|
||||
pos++;
|
||||
|
||||
/* Advance to 3.2 octet if present. */
|
||||
do {
|
||||
++pos;
|
||||
} while (pos < ie->len && !(ie->data[pos - 1] & 0x80));
|
||||
} else {
|
||||
call->ds1explicit = 0;
|
||||
}
|
||||
@@ -1324,8 +1366,12 @@ static int receive_channel_id(int full_ie, struct pri *ctrl, q931_call *call, in
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (need_extended_channel_octets && pos + 2 < len) {
|
||||
/* More coming */
|
||||
if (need_extended_channel_octets && pos + 2 <= ie->len) {
|
||||
/*
|
||||
* Octet 3.2 and at least one octet 3.3 are present.
|
||||
*
|
||||
* Process octet 3.2
|
||||
*/
|
||||
if ((ie->data[pos] & 0x0f) != 3) {
|
||||
/* Channel type/mapping is not for B channel units. */
|
||||
pri_error(ctrl, "!! Unexpected Channel Type %d\n", ie->data[pos] & 0x0f);
|
||||
@@ -1335,14 +1381,25 @@ static int receive_channel_id(int full_ie, struct pri *ctrl, q931_call *call, in
|
||||
pri_error(ctrl, "!! Invalid CCITT coding %d\n", (ie->data[pos] & 0x60) >> 5);
|
||||
return -1;
|
||||
}
|
||||
if (ie->data[pos] & 0x10) {
|
||||
/* Expect Slot Map */
|
||||
if (ie->data[pos++] & 0x10) {
|
||||
/* Process 3.3 octets as a Slot Map */
|
||||
call->slotmap = 0;
|
||||
pos++;
|
||||
call->slotmap_size = (ie->len - pos > 3) ? 1 : 0;
|
||||
for (x = 0; x < (call->slotmap_size ? 4 : 3); ++x) {
|
||||
|
||||
/*
|
||||
* We will be tolerant of partial slot maps that do not
|
||||
* specify the upper channels. We will assume they
|
||||
* are not requested.
|
||||
*
|
||||
* We will only read up to 24 or 32 bit channel maps.
|
||||
*/
|
||||
for (x = call->slotmap_size ? 4 : 3; x--;) {
|
||||
call->slotmap <<= 8;
|
||||
call->slotmap |= ie->data[x + pos];
|
||||
call->slotmap |= ie->data[pos++];
|
||||
if (ie->len <= pos) {
|
||||
/* No more ie contents. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (msgtype == Q931_RESTART) {
|
||||
@@ -1357,8 +1414,11 @@ static int receive_channel_id(int full_ie, struct pri *ctrl, q931_call *call, in
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pos++;
|
||||
/* Only expect a particular channel */
|
||||
/*
|
||||
* Process 3.3 octets as either a single channel or a channel list
|
||||
*
|
||||
* Get single channel
|
||||
*/
|
||||
call->channelno = ie->data[pos] & 0x7f;
|
||||
if (ctrl->chan_mapping_logical && call->channelno > 15) {
|
||||
call->channelno++;
|
||||
@@ -1385,6 +1445,9 @@ static int receive_channel_id(int full_ie, struct pri *ctrl, q931_call *call, in
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (need_extended_channel_octets) {
|
||||
pri_error(ctrl, "!! Missing expected Channel Identification octets 3.2 or 3.3\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1518,21 +1581,29 @@ static void dump_channel_id(int full_ie, struct pri *ctrl, q931_ie *ie, int len,
|
||||
(ie->data[0] & 0x08) ? "Exclusive" : "Preferred",
|
||||
(ie->data[0] & 0x04) ? 1 : 0);
|
||||
pri_message(ctrl, "%c ChanSel: %s\n",
|
||||
prefix, msg_chan_sel[(ie->data[0] & 0x03) | ((ie->data[0] >> 3) & 0x04)]);
|
||||
prefix, msg_chan_sel[(ie->data[0] & 0x03) | ((ie->data[0] & 0x20) >> 3)]);
|
||||
pos = 1;
|
||||
len -= 2;
|
||||
if (ie->data[0] & 0x40) {
|
||||
/* Explicitly defined DS1 */
|
||||
do {
|
||||
pri_message(ctrl, "%c Ext: %d DS1 Identifier: %d \n",
|
||||
prefix, (ie->data[pos] & 0x80) >> 7, ie->data[pos] & 0x7f);
|
||||
++pos;
|
||||
} while (!(ie->data[pos - 1] & 0x80) && pos < len);
|
||||
/* Explicitly defined DS1 (One or more 3.1 octets expected) */
|
||||
if (ctrl->switchtype == PRI_SWITCH_QSIG) {
|
||||
pri_message(ctrl, "%c Octet 3.1 specified when Q.SIG!\n",
|
||||
prefix);
|
||||
}
|
||||
if (pos < len) {
|
||||
do {
|
||||
pri_message(ctrl, "%c Ext: %d DS1 Identifier: %d\n",
|
||||
prefix, (ie->data[pos] & 0x80) >> 7, ie->data[pos] & 0x7f);
|
||||
++pos;
|
||||
} while (!(ie->data[pos - 1] & 0x80) && pos < len);
|
||||
} else {
|
||||
pri_message(ctrl, "%c Octet 3.1 is missing!\n", prefix);
|
||||
}
|
||||
} else {
|
||||
/* Implicitly defined DS1 */
|
||||
}
|
||||
if (pos < len) {
|
||||
/* Still more information here */
|
||||
/* Octet 3.2 present */
|
||||
pri_message(ctrl,
|
||||
"%c Ext: %d Coding: %d %s Specified Channel Type: %d\n",
|
||||
prefix, (ie->data[pos] & 0x80) >> 7, (ie->data[pos] & 60) >> 5,
|
||||
@@ -1540,6 +1611,7 @@ static void dump_channel_id(int full_ie, struct pri *ctrl, q931_ie *ie, int len,
|
||||
++pos;
|
||||
}
|
||||
if (pos < len) {
|
||||
/* One or more 3.3 octets present */
|
||||
if (!(ie->data[pos - 1] & 0x10)) {
|
||||
/* Number specified */
|
||||
do {
|
||||
@@ -2681,10 +2753,33 @@ static void dump_change_status(int full_ie, struct pri *ctrl, q931_ie *ie, int l
|
||||
pri_message(ctrl, " %02x", ie->data[x] & 0x7f);
|
||||
}
|
||||
pri_message(ctrl, " ]\n");
|
||||
|
||||
switch (ctrl->switchtype) {
|
||||
case PRI_SWITCH_NI2:
|
||||
case PRI_SWITCH_DMS100:
|
||||
case PRI_SWITCH_LUCENT5E:
|
||||
case PRI_SWITCH_ATT4ESS:
|
||||
break;
|
||||
default:
|
||||
/* ie not supported by this switch type */
|
||||
pri_message(ctrl, "%c %s is treated as unknown by current switch type.\n",
|
||||
prefix, ie2str(full_ie));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int receive_change_status(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
|
||||
{
|
||||
switch (ctrl->switchtype) {
|
||||
case PRI_SWITCH_NI2:
|
||||
case PRI_SWITCH_DMS100:
|
||||
case PRI_SWITCH_LUCENT5E:
|
||||
case PRI_SWITCH_ATT4ESS:
|
||||
break;
|
||||
default:
|
||||
/* ie not supported by this switch type */
|
||||
return -1;
|
||||
}
|
||||
call->changestatus = ie->data[0] & 0x0f;
|
||||
return 0;
|
||||
}
|
||||
@@ -2807,7 +2902,8 @@ static int receive_progress_indicator(int full_ie, struct pri *ctrl, q931_call *
|
||||
{
|
||||
call->progloc = ie->data[0] & 0xf;
|
||||
call->progcode = (ie->data[0] & 0x60) >> 5;
|
||||
switch (call->progress = (ie->data[1] & 0x7f)) {
|
||||
call->progress = (ie->data[1] & 0x7f);
|
||||
switch (call->progress) {
|
||||
case Q931_PROG_CALL_NOT_E2E_ISDN:
|
||||
call->progressmask |= PRI_PROG_CALL_NOT_E2E_ISDN;
|
||||
break;
|
||||
@@ -2840,7 +2936,7 @@ static int receive_progress_indicator(int full_ie, struct pri *ctrl, q931_call *
|
||||
break;
|
||||
default:
|
||||
pri_error(ctrl, "XXX Invalid Progress indicator value received: %02x\n",(ie->data[1] & 0x7f));
|
||||
break;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -3084,7 +3180,9 @@ static void q931_apdu_msg_expire(struct pri *ctrl, struct q931_call *call, int m
|
||||
|
||||
static int transmit_progress_indicator(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
|
||||
{
|
||||
int code, mask;
|
||||
int code;
|
||||
int mask;
|
||||
|
||||
/* Can't send progress indicator on GR-303 -- EVER! */
|
||||
if (ctrl->link.next && !ctrl->bri)
|
||||
return 0;
|
||||
@@ -3475,38 +3573,73 @@ static char *pri_causeclass2str(int cause)
|
||||
static void dump_cause(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
|
||||
{
|
||||
int x;
|
||||
int cause_ind = 1;
|
||||
int data_ind = 2;
|
||||
|
||||
pri_message(ctrl,
|
||||
"%c %s (len=%2d) [ Ext: %d Coding: %s (%d) Spare: %d Location: %s (%d)\n",
|
||||
prefix, ie2str(full_ie), len, ie->data[0] >> 7,
|
||||
coding2str((ie->data[0] & 0x60) >> 5), (ie->data[0] & 0x60) >> 5,
|
||||
(ie->data[0] & 0x10) >> 4, loc2str(ie->data[0] & 0xf), ie->data[0] & 0xf);
|
||||
if ((ie->data[0] & 0x80) == 0) {
|
||||
const char *recommendation;
|
||||
|
||||
switch (ie->data[1] & 0x7f) {
|
||||
case 0x00:
|
||||
recommendation = "Q.931";
|
||||
break;
|
||||
case 0x03:
|
||||
recommendation = "X.21";
|
||||
break;
|
||||
case 0x04:
|
||||
recommendation = "X.25";
|
||||
break;
|
||||
case 0x05:
|
||||
recommendation = "Q.1031/Q.1051";
|
||||
break;
|
||||
default:
|
||||
recommendation = "Reserved";
|
||||
break;
|
||||
}
|
||||
pri_message(ctrl, "%c Ext: %d Recommendation: %s (%d)\n",
|
||||
prefix, (ie->data[1] >> 7), recommendation, ie->data[1] & 0x7f);
|
||||
|
||||
cause_ind = 2;
|
||||
data_ind = 3;
|
||||
}
|
||||
pri_message(ctrl, "%c Ext: %d Cause: %s (%d), class = %s (%d) ]\n",
|
||||
prefix, (ie->data[1] >> 7), pri_cause2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f,
|
||||
pri_causeclass2str((ie->data[1] & 0x7f) >> 4), (ie->data[1] & 0x7f) >> 4);
|
||||
if (ie->len < 3)
|
||||
prefix, (ie->data[cause_ind] >> 7), pri_cause2str(ie->data[cause_ind] & 0x7f), ie->data[cause_ind] & 0x7f,
|
||||
pri_causeclass2str((ie->data[cause_ind] & 0x7f) >> 4), (ie->data[cause_ind] & 0x7f) >> 4);
|
||||
if (ie->len <= data_ind) {
|
||||
return;
|
||||
}
|
||||
/* Dump cause data in readable form */
|
||||
switch(ie->data[1] & 0x7f) {
|
||||
switch(ie->data[cause_ind] & 0x7f) {
|
||||
case PRI_CAUSE_IE_NONEXIST:
|
||||
for (x=2;x<ie->len;x++)
|
||||
for (x = data_ind; x < ie->len; x++) {
|
||||
pri_message(ctrl, "%c Cause data %d: %02x (%d, %s IE)\n", prefix, x-1, ie->data[x], ie->data[x], ie2str(ie->data[x]));
|
||||
}
|
||||
break;
|
||||
case PRI_CAUSE_WRONG_CALL_STATE:
|
||||
for (x=2;x<ie->len;x++)
|
||||
for (x = data_ind; x < ie->len; x++) {
|
||||
pri_message(ctrl, "%c Cause data %d: %02x (%d, %s message)\n", prefix, x-1, ie->data[x], ie->data[x], msg2str(ie->data[x]));
|
||||
}
|
||||
break;
|
||||
case PRI_CAUSE_RECOVERY_ON_TIMER_EXPIRE:
|
||||
pri_message(ctrl, "%c Cause data:", prefix);
|
||||
for (x=2;x<ie->len;x++)
|
||||
for (x = data_ind; x < ie->len; x++) {
|
||||
pri_message(ctrl, " %02x", ie->data[x]);
|
||||
}
|
||||
pri_message(ctrl, " (Timer T");
|
||||
for (x=2;x<ie->len;x++)
|
||||
for (x = data_ind; x < ie->len; x++) {
|
||||
pri_message(ctrl, "%c", ((ie->data[x] >= ' ') && (ie->data[x] < 0x7f)) ? ie->data[x] : '.');
|
||||
}
|
||||
pri_message(ctrl, ")\n");
|
||||
break;
|
||||
default:
|
||||
for (x=2;x<ie->len;x++)
|
||||
for (x = data_ind; x < ie->len; x++) {
|
||||
pri_message(ctrl, "%c Cause data %d: %02x (%d)\n", prefix, x-1, ie->data[x], ie->data[x]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -3515,7 +3648,11 @@ static int receive_cause(int full_ie, struct pri *ctrl, q931_call *call, int msg
|
||||
{
|
||||
call->causeloc = ie->data[0] & 0xf;
|
||||
call->causecode = (ie->data[0] & 0x60) >> 5;
|
||||
call->cause = (ie->data[1] & 0x7f);
|
||||
if (ie->data[0] & 0x80) {
|
||||
call->cause = (ie->data[1] & 0x7f);
|
||||
} else {
|
||||
call->cause = (ie->data[2] & 0x7f);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3913,8 +4050,11 @@ static int transmit_reverse_charging_indication(int full_ie, struct pri *ctrl, q
|
||||
}
|
||||
|
||||
static struct ie ies[] = {
|
||||
/* Codeset 0 - Comprehension required ie's with varying support. */
|
||||
{ 1, Q931_IE_SEGMENTED_MSG, "Segmented Message" }, /* Not supported. Just ie name is available for message decode. */
|
||||
{ 1, Q931_IE_CHANGE_STATUS, "Change Status Information", dump_change_status, receive_change_status, transmit_change_status },
|
||||
|
||||
/* Codeset 0 - Common */
|
||||
{ 1, NATIONAL_CHANGE_STATUS, "Change Status Information", dump_change_status, receive_change_status, transmit_change_status },
|
||||
{ 0, Q931_LOCKING_SHIFT, "Locking Shift", dump_shift },
|
||||
{ 0, Q931_BEARER_CAPABILITY, "Bearer Capability", dump_bearer_capability, receive_bearer_capability, transmit_bearer_capability },
|
||||
{ 0, Q931_CAUSE, "Cause", dump_cause, receive_cause, transmit_cause },
|
||||
@@ -3946,7 +4086,6 @@ static struct ie ies[] = {
|
||||
{ 1, Q931_IE_FEATURE_ACTIVATE, "Feature Activation" },
|
||||
{ 1, Q931_IE_INFO_REQUEST, "Feature Request" },
|
||||
{ 1, Q931_IE_FEATURE_IND, "Feature Indication" },
|
||||
{ 1, Q931_IE_SEGMENTED_MSG, "Segmented Message" },
|
||||
{ 1, Q931_IE_CALL_IDENTITY, "Call Identity", dump_call_identity },
|
||||
{ 1, Q931_IE_ENDPOINT_ID, "Endpoint Identification" },
|
||||
{ 1, Q931_IE_NOTIFY_IND, "Notification Indicator", dump_notify, receive_notify, transmit_notify },
|
||||
@@ -3958,7 +4097,6 @@ static struct ie ies[] = {
|
||||
{ 1, Q931_IE_USER_USER, "User-User Information", dump_user_user, receive_user_user, transmit_user_user },
|
||||
{ 1, Q931_IE_ESCAPE_FOR_EXT, "Escape for Extension" },
|
||||
{ 1, Q931_IE_CALL_STATUS, "Call Status" },
|
||||
{ 1, Q931_IE_CHANGE_STATUS, "Change Status Information", dump_change_status, receive_change_status, transmit_change_status },
|
||||
{ 1, Q931_IE_CONNECTED_ADDR, "Connected Address", dump_connected_number, receive_connected_number, transmit_connected_number },
|
||||
{ 1, Q931_IE_CONNECTED_NUM, "Connected Number", dump_connected_number, receive_connected_number, transmit_connected_number },
|
||||
{ 1, Q931_IE_CONNECTED_SUBADDR, "Connected Subaddress", dump_connected_subaddr, receive_connected_subaddr, transmit_connected_subaddr },
|
||||
@@ -4750,7 +4888,7 @@ static int add_ie(struct pri *ctrl, q931_call *call, int msgtype, int ie, q931_i
|
||||
}
|
||||
return total_res;
|
||||
} else {
|
||||
pri_error(ctrl, "!! Don't know how to add an IE %s (%d)\n", ie2str(ie), ie);
|
||||
pri_error(ctrl, "!! Don't know how to add IE %d (%s)\n", ie, ie2str(ie));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -5571,13 +5709,12 @@ int q931_notify(struct pri *ctrl, q931_call *c, int channel, int info)
|
||||
return q931_notify_redirection(ctrl, c, info, NULL, NULL);
|
||||
}
|
||||
|
||||
#ifdef ALERTING_NO_PROGRESS
|
||||
static int call_progress_ies[] = { -1 };
|
||||
#else
|
||||
static int call_progress_with_cause_ies[] = { Q931_CAUSE, Q931_PROGRESS_INDICATOR, -1 };
|
||||
|
||||
static int call_progress_ies[] = { Q931_PROGRESS_INDICATOR, -1 };
|
||||
static int call_progress_ies[] = {
|
||||
#ifndef ALERTING_NO_PROGRESS
|
||||
Q931_PROGRESS_INDICATOR,
|
||||
#endif
|
||||
-1
|
||||
};
|
||||
|
||||
int q931_call_progress(struct pri *ctrl, q931_call *c, int channel, int info)
|
||||
{
|
||||
@@ -5605,6 +5742,14 @@ int q931_call_progress(struct pri *ctrl, q931_call *c, int channel, int info)
|
||||
return send_message(ctrl, c, Q931_PROGRESS, call_progress_ies);
|
||||
}
|
||||
|
||||
static int call_progress_with_cause_ies[] = {
|
||||
Q931_CAUSE,
|
||||
#ifndef ALERTING_NO_PROGRESS
|
||||
Q931_PROGRESS_INDICATOR,
|
||||
#endif
|
||||
-1
|
||||
};
|
||||
|
||||
int q931_call_progress_with_cause(struct pri *ctrl, q931_call *c, int channel, int info, int cause)
|
||||
{
|
||||
if (c->ourcallstate == Q931_CALL_STATE_CALL_INDEPENDENT_SERVICE) {
|
||||
@@ -5635,11 +5780,13 @@ int q931_call_progress_with_cause(struct pri *ctrl, q931_call *c, int channel, i
|
||||
return send_message(ctrl, c, Q931_PROGRESS, call_progress_with_cause_ies);
|
||||
}
|
||||
|
||||
#ifdef ALERTING_NO_PROGRESS
|
||||
static int call_proceeding_ies[] = { Q931_CHANNEL_IDENT, -1 };
|
||||
#else
|
||||
static int call_proceeding_ies[] = { Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, -1 };
|
||||
static int call_proceeding_ies[] = {
|
||||
Q931_CHANNEL_IDENT,
|
||||
#ifndef ALERTING_NO_PROGRESS
|
||||
Q931_PROGRESS_INDICATOR,
|
||||
#endif
|
||||
-1
|
||||
};
|
||||
|
||||
int q931_call_proceeding(struct pri *ctrl, q931_call *c, int channel, int info)
|
||||
{
|
||||
@@ -5670,11 +5817,15 @@ int q931_call_proceeding(struct pri *ctrl, q931_call *c, int channel, int info)
|
||||
c->alive = 1;
|
||||
return send_message(ctrl, c, Q931_CALL_PROCEEDING, call_proceeding_ies);
|
||||
}
|
||||
|
||||
static int alerting_ies[] = {
|
||||
Q931_IE_FACILITY,
|
||||
#ifndef ALERTING_NO_PROGRESS
|
||||
static int alerting_ies[] = { Q931_IE_FACILITY, Q931_PROGRESS_INDICATOR, Q931_IE_USER_USER, -1 };
|
||||
#else
|
||||
static int alerting_ies[] = { Q931_IE_FACILITY, -1 };
|
||||
Q931_PROGRESS_INDICATOR,
|
||||
#endif
|
||||
Q931_IE_USER_USER,
|
||||
-1
|
||||
};
|
||||
|
||||
int q931_alerting(struct pri *ctrl, q931_call *c, int channel, int info)
|
||||
{
|
||||
@@ -5712,9 +5863,14 @@ int q931_alerting(struct pri *ctrl, q931_call *c, int channel, int info)
|
||||
return send_message(ctrl, c, Q931_ALERTING, alerting_ies);
|
||||
}
|
||||
|
||||
static int setup_ack_ies[] = { Q931_CHANNEL_IDENT, Q931_IE_FACILITY, Q931_PROGRESS_INDICATOR, -1 };
|
||||
static int setup_ack_ies[] = {
|
||||
Q931_CHANNEL_IDENT,
|
||||
Q931_IE_FACILITY,
|
||||
Q931_PROGRESS_INDICATOR,
|
||||
-1
|
||||
};
|
||||
|
||||
int q931_setup_ack(struct pri *ctrl, q931_call *c, int channel, int nonisdn)
|
||||
int q931_setup_ack(struct pri *ctrl, q931_call *c, int channel, int nonisdn, int inband)
|
||||
{
|
||||
if (c->ourcallstate == Q931_CALL_STATE_CALL_INDEPENDENT_SERVICE) {
|
||||
/* Cannot send this message when in this state */
|
||||
@@ -5727,12 +5883,20 @@ int q931_setup_ack(struct pri *ctrl, q931_call *c, int channel, int nonisdn)
|
||||
}
|
||||
c->chanflags &= ~FLAG_PREFERRED;
|
||||
c->chanflags |= FLAG_EXCLUSIVE;
|
||||
|
||||
c->progressmask = 0;
|
||||
if (nonisdn && (ctrl->switchtype != PRI_SWITCH_DMS100)) {
|
||||
c->progloc = LOC_PRIV_NET_LOCAL_USER;
|
||||
c->progloc = LOC_PRIV_NET_LOCAL_USER;
|
||||
c->progcode = CODE_CCITT;
|
||||
c->progressmask = PRI_PROG_CALLED_NOT_ISDN;
|
||||
} else
|
||||
c->progressmask = 0;
|
||||
c->progressmask |= PRI_PROG_CALLED_NOT_ISDN;
|
||||
}
|
||||
if (inband) {
|
||||
/* Inband audio is present (i.e. dialtone) */
|
||||
c->progloc = LOC_PRIV_NET_LOCAL_USER;
|
||||
c->progcode = CODE_CCITT;
|
||||
c->progressmask |= PRI_PROG_INBAND_AVAILABLE;
|
||||
}
|
||||
|
||||
UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_OVERLAP_RECEIVING);
|
||||
c->peercallstate = Q931_CALL_STATE_OVERLAP_SENDING;
|
||||
c->alive = 1;
|
||||
@@ -5833,7 +5997,7 @@ int q931_connect(struct pri *ctrl, q931_call *c, int channel, int nonisdn)
|
||||
c->chanflags &= ~FLAG_PREFERRED;
|
||||
c->chanflags |= FLAG_EXCLUSIVE;
|
||||
if (nonisdn && (ctrl->switchtype != PRI_SWITCH_DMS100)) {
|
||||
c->progloc = LOC_PRIV_NET_LOCAL_USER;
|
||||
c->progloc = LOC_PRIV_NET_LOCAL_USER;
|
||||
c->progcode = CODE_CCITT;
|
||||
c->progressmask = PRI_PROG_CALLED_NOT_ISDN;
|
||||
} else
|
||||
@@ -6224,6 +6388,9 @@ int q931_setup(struct pri *ctrl, q931_call *c, struct pri_sr *req)
|
||||
c->chanflags = FLAG_PREFERRED;
|
||||
}
|
||||
}
|
||||
if (ctrl->localtype == PRI_CPE) {
|
||||
c->channel_id_ie_mandatory = 1;
|
||||
}
|
||||
|
||||
c->slotmap = -1;
|
||||
c->nonisdn = req->nonisdn;
|
||||
@@ -7200,6 +7367,7 @@ static int prepare_to_handle_q931_message(struct pri *ctrl, q931_mh *mh, q931_ca
|
||||
c->useruserinfo[0] = '\0';
|
||||
c->cause = -1;
|
||||
/* Fall through */
|
||||
case Q931_SETUP_ACKNOWLEDGE:
|
||||
case Q931_CALL_PROCEEDING:
|
||||
c->progress = -1;
|
||||
c->progressmask = 0;
|
||||
@@ -7213,6 +7381,8 @@ static int prepare_to_handle_q931_message(struct pri *ctrl, q931_mh *mh, q931_ca
|
||||
c->cause = -1;
|
||||
c->causecode = -1;
|
||||
c->causeloc = -1;
|
||||
c->progress = -1;
|
||||
c->progressmask = 0;
|
||||
c->aoc_units = -1;
|
||||
pri_schedule_del(ctrl, c->retranstimer);
|
||||
c->retranstimer = 0;
|
||||
@@ -7246,8 +7416,6 @@ static int prepare_to_handle_q931_message(struct pri *ctrl, q931_mh *mh, q931_ca
|
||||
break;
|
||||
case Q931_STATUS_ENQUIRY:
|
||||
break;
|
||||
case Q931_SETUP_ACKNOWLEDGE:
|
||||
break;
|
||||
case Q931_NOTIFY:
|
||||
c->notify = -1;
|
||||
q931_party_number_init(&c->redirection_number);
|
||||
@@ -7419,12 +7587,13 @@ int q931_receive(struct q921_link *link, q931_h *h, int len)
|
||||
int res;
|
||||
int r;
|
||||
int mandies[MAX_MAND_IES];
|
||||
int missingmand;
|
||||
int is_mandatory;
|
||||
int codeset, cur_codeset;
|
||||
int last_ie[8];
|
||||
int cref;
|
||||
int allow_event;
|
||||
int allow_posthandle;
|
||||
enum mandatory_ie_status mand_status;
|
||||
|
||||
ctrl = link->ctrl;
|
||||
memset(last_ie, 0, sizeof(last_ie));
|
||||
@@ -7504,7 +7673,7 @@ int q931_receive(struct q921_link *link, q931_h *h, int len)
|
||||
q931_clr_subcommands(ctrl);
|
||||
q931_display_clear(c);
|
||||
|
||||
/* Handle IEs */
|
||||
/* Determine which ies are mandatory for this message. */
|
||||
memset(mandies, 0, sizeof(mandies));
|
||||
for (x = 0; x < ARRAY_LEN(msgs); ++x) {
|
||||
if (msgs[x].msgnum == mh->msg) {
|
||||
@@ -7512,6 +7681,25 @@ int q931_receive(struct q921_link *link, q931_h *h, int len)
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (x = 0; x < ARRAY_LEN(mandies); ++x) {
|
||||
if (mandies[x]) {
|
||||
/* Check mandatory channel identification ie exceptions */
|
||||
if (mandies[x] != Q931_CHANNEL_IDENT
|
||||
/* Always mandatory for RESUME_ACKNOWLEDGE */
|
||||
|| mh->msg == Q931_RESUME_ACKNOWLEDGE
|
||||
/* Mandatory in Net -> CPE direction for SETUP */
|
||||
|| (mh->msg == Q931_SETUP && ctrl->localtype == PRI_CPE)
|
||||
/* Mandatory for first SETUP response message in Net -> CPE direction. */
|
||||
|| c->channel_id_ie_mandatory) {
|
||||
/* ie is mandatory for this message */
|
||||
continue;
|
||||
}
|
||||
/* ie is not mandatory for this message */
|
||||
mandies[x] = 0;
|
||||
}
|
||||
}
|
||||
mand_status = MAND_STATUS_OK;
|
||||
|
||||
/* Do real IE processing */
|
||||
len -= (h->crlen + 3);
|
||||
codeset = cur_codeset = 0;
|
||||
@@ -7528,10 +7716,16 @@ int q931_receive(struct q921_link *link, q931_h *h, int len)
|
||||
q931_display_clear(c);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check if processing a mandatory ie. */
|
||||
is_mandatory = 0;
|
||||
for (y = 0; y < ARRAY_LEN(mandies); ++y) {
|
||||
if (mandies[y] == Q931_FULL_IE(cur_codeset, ie->ie))
|
||||
if (mandies[y] == Q931_FULL_IE(cur_codeset, ie->ie)) {
|
||||
mandies[y] = 0;
|
||||
is_mandatory = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Special processing for codeset shifts */
|
||||
switch (ie->ie & 0xf8) {
|
||||
case Q931_LOCKING_SHIFT:
|
||||
@@ -7574,6 +7768,15 @@ int q931_receive(struct q921_link *link, q931_h *h, int len)
|
||||
/* Fall through */
|
||||
default:
|
||||
y = q931_handle_ie(cur_codeset, ctrl, c, mh->msg, ie);
|
||||
if (y < 0 && is_mandatory) {
|
||||
/* Error processing mandatory ie. */
|
||||
mand_status = MAND_STATUS_CONTENT_ERROR;
|
||||
pri_error(ctrl, "%s: Error in mandatory IE %d (cs%d, %s)\n",
|
||||
msg2str(mh->msg),
|
||||
ie->ie,
|
||||
cur_codeset,
|
||||
ie2str(Q931_FULL_IE(codeset, ie->ie)));
|
||||
}
|
||||
/* XXX Applicable to codeset 0 only? XXX */
|
||||
if (!cur_codeset && !(ie->ie & 0xf0) && (y < 0)) {
|
||||
/*
|
||||
@@ -7590,19 +7793,21 @@ int q931_receive(struct q921_link *link, q931_h *h, int len)
|
||||
break;
|
||||
}
|
||||
}
|
||||
missingmand = 0;
|
||||
|
||||
/* Check for missing mandatory ies. */
|
||||
for (x = 0; x < ARRAY_LEN(mandies); ++x) {
|
||||
if (mandies[x]) {
|
||||
/* check if there is no channel identification when we're configured as network -> that's not an error */
|
||||
if (((ctrl->localtype != PRI_NETWORK) || (mh->msg != Q931_SETUP) || (mandies[x] != Q931_CHANNEL_IDENT)) &&
|
||||
((mh->msg != Q931_PROGRESS) || (mandies[x] != Q931_PROGRESS_INDICATOR))) {
|
||||
pri_error(ctrl, "XXX Missing handling for mandatory IE %d (cs%d, %s) XXX\n", Q931_IE_IE(mandies[x]), Q931_IE_CODESET(mandies[x]), ie2str(mandies[x]));
|
||||
missingmand++;
|
||||
}
|
||||
/* This mandatory ie was not processed. */
|
||||
mand_status = MAND_STATUS_MISSING;
|
||||
pri_error(ctrl, "%s: Missing mandatory IE %d (cs%d, %s)\n",
|
||||
msg2str(mh->msg),
|
||||
Q931_IE_IE(mandies[x]),
|
||||
Q931_IE_CODESET(mandies[x]),
|
||||
ie2str(mandies[x]));
|
||||
}
|
||||
}
|
||||
|
||||
if (!missingmand) {
|
||||
if (mand_status == MAND_STATUS_OK) {
|
||||
switch (mh->msg) {
|
||||
case Q931_SETUP:
|
||||
case Q931_CONNECT:
|
||||
@@ -7638,7 +7843,7 @@ int q931_receive(struct q921_link *link, q931_h *h, int len)
|
||||
}
|
||||
|
||||
if (allow_posthandle) {
|
||||
res = post_handle_q931_message(ctrl, mh, c, missingmand);
|
||||
res = post_handle_q931_message(ctrl, mh, c, mand_status);
|
||||
if (res == Q931_RES_HAVEEVENT && !allow_event) {
|
||||
res = 0;
|
||||
}
|
||||
@@ -8508,7 +8713,7 @@ static void q931_restart_notify(struct q931_call *call)
|
||||
* \param ctrl D channel controller.
|
||||
* \param mh Q.931 message header.
|
||||
* \param c Q.931 call leg.
|
||||
* \param missingmand Number of missing mandatory ie's.
|
||||
* \param mand_status Mandatory ie status
|
||||
*
|
||||
* \note
|
||||
* When this function returns c may be destroyed so you can no
|
||||
@@ -8518,19 +8723,33 @@ static void q931_restart_notify(struct q931_call *call)
|
||||
* \retval Q931_RES_HAVEEVENT if have an event.
|
||||
* \retval -1 on error.
|
||||
*/
|
||||
static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct q931_call *c, int missingmand)
|
||||
static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct q931_call *c, enum mandatory_ie_status mand_status)
|
||||
{
|
||||
int res;
|
||||
int changed;
|
||||
int mand_cause;
|
||||
enum Q931_CALL_STATE ourcallstate_orig;
|
||||
struct apdu_event *cur = NULL;
|
||||
struct pri_subcommand *subcmd;
|
||||
struct q931_call *master_call;
|
||||
|
||||
mand_cause = 0;
|
||||
switch (mand_status) {
|
||||
case MAND_STATUS_OK:
|
||||
break;
|
||||
case MAND_STATUS_CONTENT_ERROR:
|
||||
mand_cause = PRI_CAUSE_INVALID_IE_CONTENTS;
|
||||
break;
|
||||
case MAND_STATUS_MISSING:
|
||||
mand_cause = PRI_CAUSE_MANDATORY_IE_MISSING;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(mh->msg) {
|
||||
case Q931_RESTART:
|
||||
q931_display_subcmd(ctrl, c);
|
||||
if (missingmand) {
|
||||
q931_status(ctrl, c, PRI_CAUSE_MANDATORY_IE_MISSING);
|
||||
if (mand_status != MAND_STATUS_OK) {
|
||||
q931_status(ctrl, c, mand_cause);
|
||||
pri_destroycall(ctrl, c);
|
||||
break;
|
||||
}
|
||||
@@ -8588,9 +8807,8 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
||||
return Q931_RES_HAVEEVENT;
|
||||
case Q931_SETUP:
|
||||
q931_display_subcmd(ctrl, c);
|
||||
|
||||
if (missingmand) {
|
||||
q931_release_complete(ctrl, c, PRI_CAUSE_MANDATORY_IE_MISSING);
|
||||
if (mand_status != MAND_STATUS_OK) {
|
||||
q931_release_complete(ctrl, c, mand_cause);
|
||||
break;
|
||||
}
|
||||
/* Must be new call */
|
||||
@@ -8633,11 +8851,24 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
||||
return Q931_RES_HAVEEVENT;
|
||||
case Q931_ALERTING:
|
||||
q931_display_subcmd(ctrl, c);
|
||||
if (mand_status != MAND_STATUS_OK) {
|
||||
q931_status(ctrl, c, mand_cause);
|
||||
break;
|
||||
}
|
||||
stop_t303(c->master_call);
|
||||
if (c->newcall) {
|
||||
q931_release_complete(ctrl, c, newcall_rel_comp_cause(c));
|
||||
break;
|
||||
}
|
||||
switch (c->ourcallstate) {
|
||||
default:
|
||||
q931_status(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
|
||||
return 0;
|
||||
case Q931_CALL_STATE_CALL_INITIATED:
|
||||
case Q931_CALL_STATE_OVERLAP_SENDING:
|
||||
case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
|
||||
break;
|
||||
}
|
||||
UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_CALL_DELIVERED);
|
||||
c->peercallstate = Q931_CALL_STATE_CALL_RECEIVED;
|
||||
ctrl->ev.e = PRI_EVENT_RINGING;
|
||||
@@ -8669,6 +8900,10 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
||||
return Q931_RES_HAVEEVENT;
|
||||
case Q931_CONNECT:
|
||||
q931_display_subcmd(ctrl, c);
|
||||
if (mand_status != MAND_STATUS_OK) {
|
||||
q931_status(ctrl, c, mand_cause);
|
||||
break;
|
||||
}
|
||||
stop_t303(c->master_call);
|
||||
if (c->newcall) {
|
||||
q931_release_complete(ctrl, c, newcall_rel_comp_cause(c));
|
||||
@@ -8747,16 +8982,15 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
||||
}
|
||||
break;
|
||||
case Q931_PROGRESS:
|
||||
if (missingmand) {
|
||||
q931_status(ctrl, c, PRI_CAUSE_MANDATORY_IE_MISSING);
|
||||
pri_destroycall(ctrl, c);
|
||||
break;
|
||||
}
|
||||
ctrl->ev.e = PRI_EVENT_PROGRESS;
|
||||
ctrl->ev.proceeding.cause = c->cause;
|
||||
/* Fall through */
|
||||
case Q931_CALL_PROCEEDING:
|
||||
q931_display_subcmd(ctrl, c);
|
||||
if (mand_status != MAND_STATUS_OK) {
|
||||
q931_status(ctrl, c, mand_cause);
|
||||
break;
|
||||
}
|
||||
stop_t303(c->master_call);
|
||||
ctrl->ev.proceeding.subcmds = &ctrl->subcmds;
|
||||
if (c->newcall) {
|
||||
@@ -8767,6 +9001,18 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
||||
(c->ourcallstate != Q931_CALL_STATE_OVERLAP_SENDING) &&
|
||||
(c->ourcallstate != Q931_CALL_STATE_CALL_DELIVERED) &&
|
||||
(c->ourcallstate != Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING)) {
|
||||
if (mh->msg == Q931_PROGRESS
|
||||
&& c->ourcallstate == Q931_CALL_STATE_ACTIVE
|
||||
&& ctrl->switchtype == PRI_SWITCH_QSIG) {
|
||||
/*
|
||||
* Q.SIG is odd to allow PROGRESS when in the Active state since
|
||||
* the media path is already open. Ignore it since it doesn't
|
||||
* convey anything very useful. Maybe they will stop doing it.
|
||||
*
|
||||
* See ECMA-143 Section 10.1.7.2.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
q931_status(ctrl,c,PRI_CAUSE_WRONG_MESSAGE);
|
||||
break;
|
||||
}
|
||||
@@ -8796,11 +9042,8 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
||||
}
|
||||
switch (c->ourcallstate) {
|
||||
default:
|
||||
if (ctrl->localtype == PRI_NETWORK || ctrl->switchtype == PRI_SWITCH_QSIG) {
|
||||
q931_status(ctrl, c, PRI_CAUSE_WRONG_MESSAGE);
|
||||
break;
|
||||
}
|
||||
/* Fall through */
|
||||
q931_status(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
|
||||
return 0;
|
||||
case Q931_CALL_STATE_CONNECT_REQUEST:
|
||||
case Q931_CALL_STATE_ACTIVE:
|
||||
UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_ACTIVE);
|
||||
@@ -8817,9 +9060,8 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
||||
break;
|
||||
case Q931_STATUS:
|
||||
q931_display_subcmd(ctrl, c);
|
||||
if (missingmand) {
|
||||
q931_status(ctrl, c, PRI_CAUSE_MANDATORY_IE_MISSING);
|
||||
pri_destroycall(ctrl, c);
|
||||
if (mand_status != MAND_STATUS_OK) {
|
||||
q931_status(ctrl, c, mand_cause);
|
||||
break;
|
||||
}
|
||||
if (c->newcall) {
|
||||
@@ -8925,9 +9167,9 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
||||
case Q931_RELEASE:
|
||||
q931_display_subcmd(ctrl, c);
|
||||
c->hangupinitiated = 1;
|
||||
if (missingmand) {
|
||||
/* Force cause to be mandatory IE missing */
|
||||
c->cause = PRI_CAUSE_MANDATORY_IE_MISSING;
|
||||
if (mand_status != MAND_STATUS_OK) {
|
||||
/* Force mandatory ie cause */
|
||||
c->cause = mand_cause;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -8971,9 +9213,9 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
||||
case Q931_DISCONNECT:
|
||||
q931_display_subcmd(ctrl, c);
|
||||
c->hangupinitiated = 1;
|
||||
if (missingmand) {
|
||||
if (mand_status != MAND_STATUS_OK) {
|
||||
/* Still let user call release */
|
||||
c->cause = PRI_CAUSE_MANDATORY_IE_MISSING;
|
||||
c->cause = mand_cause;
|
||||
}
|
||||
if (c->newcall) {
|
||||
q931_release_complete(ctrl, c, newcall_rel_comp_cause(c));
|
||||
@@ -9026,14 +9268,46 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
||||
}
|
||||
}
|
||||
|
||||
ourcallstate_orig = c->ourcallstate;
|
||||
UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_DISCONNECT_INDICATION);
|
||||
c->peercallstate = Q931_CALL_STATE_DISCONNECT_REQUEST;
|
||||
c->sendhangupack = 1;
|
||||
|
||||
/* wait for a RELEASE so that sufficient time has passed
|
||||
for the inband audio to be heard */
|
||||
if (ctrl->acceptinbanddisconnect && (c->progressmask & PRI_PROG_INBAND_AVAILABLE))
|
||||
if (ctrl->acceptinbanddisconnect
|
||||
&& (c->progressmask & PRI_PROG_INBAND_AVAILABLE)) {
|
||||
switch (ourcallstate_orig) {
|
||||
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:
|
||||
/*
|
||||
* Open the media path if it isn't already open so
|
||||
* the user can hear the inband audio.
|
||||
*/
|
||||
if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
|
||||
pri_message(ctrl, "Report the DISCONNECT as a PROGRESS instead.\n");
|
||||
}
|
||||
ctrl->ev.e = PRI_EVENT_PROGRESS;
|
||||
ctrl->ev.proceeding.cause = c->cause;
|
||||
ctrl->ev.proceeding.subcmds = &ctrl->subcmds;
|
||||
ctrl->ev.proceeding.channel = q931_encode_channel(c);
|
||||
ctrl->ev.proceeding.progress = c->progress;
|
||||
ctrl->ev.proceeding.progressmask = c->progressmask;
|
||||
ctrl->ev.proceeding.cref = c->cr;
|
||||
ctrl->ev.proceeding.call = c->master_call;
|
||||
return Q931_RES_HAVEEVENT;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Suppress reporting DISCONNECT to the upper layer. The
|
||||
* media path should already be open and we cannot report
|
||||
* a PROGRESS at this time anyway.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
/* Return such an event */
|
||||
ctrl->ev.e = PRI_EVENT_HANGUP_REQ;
|
||||
@@ -9100,7 +9374,7 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
||||
q931_release_complete(ctrl, c, newcall_rel_comp_cause(c));
|
||||
break;
|
||||
}
|
||||
if (c->ourcallstate != Q931_CALL_STATE_OVERLAP_RECEIVING) {
|
||||
if (strlen(c->keypad_digits)) {
|
||||
ctrl->ev.e = PRI_EVENT_KEYPAD_DIGIT;
|
||||
ctrl->ev.digit.subcmds = &ctrl->subcmds;
|
||||
ctrl->ev.digit.call = c->master_call;
|
||||
@@ -9133,17 +9407,29 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
||||
break;
|
||||
case Q931_SETUP_ACKNOWLEDGE:
|
||||
q931_display_subcmd(ctrl, c);
|
||||
if (mand_status != MAND_STATUS_OK) {
|
||||
q931_status(ctrl, c, mand_cause);
|
||||
break;
|
||||
}
|
||||
stop_t303(c->master_call);
|
||||
if (c->newcall) {
|
||||
q931_release_complete(ctrl, c, newcall_rel_comp_cause(c));
|
||||
break;
|
||||
}
|
||||
switch (c->ourcallstate) {
|
||||
default:
|
||||
q931_status(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
|
||||
return 0;
|
||||
case Q931_CALL_STATE_CALL_INITIATED:
|
||||
break;
|
||||
}
|
||||
UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_OVERLAP_SENDING);
|
||||
c->peercallstate = Q931_CALL_STATE_OVERLAP_RECEIVING;
|
||||
ctrl->ev.e = PRI_EVENT_SETUP_ACK;
|
||||
ctrl->ev.setup_ack.subcmds = &ctrl->subcmds;
|
||||
ctrl->ev.setup_ack.channel = q931_encode_channel(c);
|
||||
ctrl->ev.setup_ack.call = c->master_call;
|
||||
ctrl->ev.setup_ack.progressmask = c->progressmask;
|
||||
|
||||
for (cur = c->apdus; cur; cur = cur->next) {
|
||||
if (!cur->sent && cur->message == Q931_FACILITY) {
|
||||
@@ -9350,9 +9636,9 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
||||
master_call = c->master_call;
|
||||
switch (master_call->hold_state) {
|
||||
case Q931_HOLD_STATE_HOLD_REQ:
|
||||
if (missingmand) {
|
||||
if (mand_status != MAND_STATUS_OK) {
|
||||
/* Still, let hold rejection continue. */
|
||||
c->cause = PRI_CAUSE_MANDATORY_IE_MISSING;
|
||||
c->cause = mand_cause;
|
||||
}
|
||||
ctrl->ev.e = PRI_EVENT_HOLD_REJ;
|
||||
ctrl->ev.hold_rej.channel = q931_encode_channel(c);
|
||||
@@ -9474,9 +9760,9 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
||||
pri_schedule_del(ctrl, master_call->hold_timer);
|
||||
master_call->hold_timer = 0;
|
||||
|
||||
if (missingmand) {
|
||||
if (mand_status != MAND_STATUS_OK) {
|
||||
/* Still, let retrive rejection continue. */
|
||||
c->cause = PRI_CAUSE_MANDATORY_IE_MISSING;
|
||||
c->cause = mand_cause;
|
||||
}
|
||||
ctrl->ev.e = PRI_EVENT_RETRIEVE_REJ;
|
||||
ctrl->ev.retrieve_rej.channel = q931_encode_channel(c);
|
||||
|
||||
Reference in New Issue
Block a user