summaryrefslogtreecommitdiff
path: root/channels/sig_pri.c
diff options
context:
space:
mode:
authorKinsey Moore <kmoore@digium.com>2012-06-22 15:10:38 +0000
committerKinsey Moore <kmoore@digium.com>2012-06-22 15:10:38 +0000
commit1ab47ac13732ec146a9533c157427bfa152cb4c1 (patch)
tree688dd14555d4d520a95c06209e5105245cdb3d99 /channels/sig_pri.c
parentdee5d6b9e5ddd1659e6038ec47d6bcce32c5cb6f (diff)
Add HANGUPCAUSE hash support for analog and PRI DAHDI subtechs
This is part of the DAHDI support for the Asterisk 11 "Who Hung Up?" project and covers the implementation for the technologies implemented in sig_analog.c and sig_pri.c. Tested on a local machine to verify protocol and cause information is available. Review: https://reviewboard.asterisk.org/r/1953/ (issue SWP-4222) git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@369185 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels/sig_pri.c')
-rw-r--r--channels/sig_pri.c69
1 files changed, 68 insertions, 1 deletions
diff --git a/channels/sig_pri.c b/channels/sig_pri.c
index 93b9b4b8b..ead02f587 100644
--- a/channels/sig_pri.c
+++ b/channels/sig_pri.c
@@ -1261,6 +1261,37 @@ static void pri_queue_control(struct sig_pri_span *pri, int chanpos, int subclas
/*!
* \internal
+ * \brief Queue a PVT_CAUSE_CODE frame onto the owner channel.
+ * \since 11
+ *
+ * \param pri PRI span control structure.
+ * \param chanpos Channel position in the span.
+ * \param cause String describing the cause to be placed into the frame.
+ *
+ * \note Assumes the pri->lock is already obtained.
+ * \note Assumes the sig_pri_lock_private(pri->pvts[chanpos]) is already obtained.
+ *
+ * \return Nothing
+ */
+static void pri_queue_pvt_cause_data(struct sig_pri_span *pri, int chanpos, const char *cause)
+{
+ struct ast_channel *chan;
+ struct ast_control_pvt_cause_code *cause_code;
+
+ sig_pri_lock_owner(pri, chanpos);
+ chan = pri->pvts[chanpos]->owner;
+ if (chan) {
+ int datalen = sizeof(*cause_code) + strlen(cause);
+ cause_code = alloca(datalen);
+ ast_copy_string(cause_code->chan_name, ast_channel_name(chan), AST_CHANNEL_NAME);
+ ast_copy_string(cause_code->code, cause, datalen + 1 - sizeof(*cause_code));
+ ast_queue_control_data(chan, AST_CONTROL_PVT_CAUSE_CODE, cause_code, datalen);
+ ast_channel_unlock(chan);
+ }
+}
+
+/*!
+ * \internal
* \brief Find the channel associated with the libpri call.
* \since 10.0
*
@@ -5440,7 +5471,6 @@ static void *pri_dchannel(void *vpri)
pri_event *e;
struct pollfd fds[SIG_PRI_NUM_DCHANS];
int res;
- int chanpos = 0;
int x;
int law;
struct ast_channel *c;
@@ -5648,6 +5678,9 @@ static void *pri_dchannel(void *vpri)
ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
if (e) {
+ int chanpos = -1;
+ char cause_str[35];
+
if (pri->debug) {
ast_verbose("Span %d: Processing event %s(%d)\n",
pri->span, pri_event2str(e->e), e->e);
@@ -6448,6 +6481,11 @@ static void *pri_dchannel(void *vpri)
e->proceeding.call);
if (e->proceeding.cause > -1) {
+ if (pri->pvts[chanpos]->owner) {
+ snprintf(cause_str, sizeof(cause_str), "PRI PRI_EVENT_PROGRESS (%d)", e->proceeding.cause);
+ pri_queue_pvt_cause_data(pri, chanpos, cause_str);
+ }
+
ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
/* Work around broken, out of spec USER_BUSY cause in a progress message */
@@ -6459,6 +6497,8 @@ static void *pri_dchannel(void *vpri)
pri_queue_control(pri, chanpos, AST_CONTROL_BUSY);
}
}
+ } else if (pri->pvts[chanpos]->owner) {
+ pri_queue_pvt_cause_data(pri, chanpos, "PRI PRI_EVENT_PROGRESS");
}
if (!pri->pvts[chanpos]->progress
@@ -6736,6 +6776,9 @@ static void *pri_dchannel(void *vpri)
if (pri->pvts[chanpos]->owner) {
int do_hangup = 0;
+ snprintf(cause_str, sizeof(cause_str), "PRI PRI_EVENT_HANGUP (%d)", e->hangup.cause);
+ pri_queue_pvt_cause_data(pri, chanpos, cause_str);
+
/* Queue a BUSY instead of a hangup if our cause is appropriate */
ast_channel_hangupcause_set(pri->pvts[chanpos]->owner, e->hangup.cause);
switch (ast_channel_state(pri->pvts[chanpos]->owner)) {
@@ -6885,6 +6928,9 @@ static void *pri_dchannel(void *vpri)
if (pri->pvts[chanpos]->owner) {
int do_hangup = 0;
+ snprintf(cause_str, sizeof(cause_str), "PRI PRI_EVENT_HANGUP_REQ (%d)", e->hangup.cause);
+ pri_queue_pvt_cause_data(pri, chanpos, cause_str);
+
ast_channel_hangupcause_set(pri->pvts[chanpos]->owner, e->hangup.cause);
switch (ast_channel_state(pri->pvts[chanpos]->owner)) {
case AST_STATE_BUSY:
@@ -7218,6 +7264,27 @@ static void *pri_dchannel(void *vpri)
pri->span, pri_event2str(e->e), e->e);
break;
}
+
+ /* send tech-specific information for HANGUPCAUSE hash */
+ if (chanpos > -1 && pri->pvts[chanpos]) {
+ switch (e->e) {
+ /* already handled above */
+ case PRI_EVENT_PROGRESS:
+ case PRI_EVENT_HANGUP:
+ case PRI_EVENT_HANGUP_REQ:
+ break;
+ default:
+ sig_pri_lock_private(pri->pvts[chanpos]);
+ if (pri->pvts[chanpos]->owner) {
+ char *event_str = pri_event2str(e->e);
+
+ snprintf(cause_str, sizeof(cause_str), "PRI %s", event_str);
+ pri_queue_pvt_cause_data(pri, chanpos, cause_str);
+ }
+ sig_pri_unlock_private(pri->pvts[chanpos]);
+ break;
+ }
+ }
}
ast_mutex_unlock(&pri->lock);
}