aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xcdr.c46
-rwxr-xr-xchannel.c37
-rwxr-xr-xchannels/chan_zap.c19
-rwxr-xr-xinclude/asterisk/cdr.h16
-rwxr-xr-xinclude/asterisk/channel.h3
-rwxr-xr-xpbx.c23
6 files changed, 130 insertions, 14 deletions
diff --git a/cdr.c b/cdr.c
index 20b3e2cfa..3cbaac47e 100755
--- a/cdr.c
+++ b/cdr.c
@@ -19,6 +19,7 @@
#include <asterisk/cdr.h>
#include <asterisk/logger.h>
#include <asterisk/callerid.h>
+#include <asterisk/causes.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
@@ -163,6 +164,41 @@ void ast_cdr_busy(struct ast_cdr *cdr)
}
}
+void ast_cdr_failed(struct ast_cdr *cdr)
+{
+ char *chan;
+ if (cdr) {
+ chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
+ if (cdr->posted)
+ ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
+ cdr->disposition = AST_CDR_FAILED;
+ }
+}
+
+int ast_cdr_disposition(struct ast_cdr *cdr, int cause)
+{
+ int res = 0;
+ if (cdr) {
+ switch(cause) {
+ case AST_CAUSE_BUSY:
+ ast_cdr_busy(cdr);
+ break;
+ case AST_CAUSE_FAILURE:
+ ast_cdr_failed(cdr);
+ break;
+ case AST_CAUSE_NORMAL:
+ break;
+ case AST_CAUSE_NOTDEFINED:
+ res = -1;
+ break;
+ default:
+ res = -1;
+ ast_log(LOG_WARNING, "We don't handle that cause yet\n");
+ }
+ }
+ return res;
+}
+
void ast_cdr_setdestchan(struct ast_cdr *cdr, char *chann)
{
char *chan;
@@ -275,6 +311,8 @@ char *ast_cdr_disp2str(int disposition)
switch (disposition) {
case AST_CDR_NOANSWER:
return "NO ANSWER";
+ case AST_CDR_FAILED:
+ return "FAILED";
case AST_CDR_BUSY:
return "BUSY";
case AST_CDR_ANSWERED:
@@ -313,11 +351,15 @@ int ast_cdr_update(struct ast_channel *c)
char *name, *num;
char tmp[AST_MAX_EXTENSION] = "";
/* Grab source from ANI or normal Caller*ID */
+ if (!cdr) {
+ ast_log(LOG_NOTICE, "The cdr pointer is not set\n");
+ return -1;
+ }
if (c->ani)
strncpy(tmp, c->ani, sizeof(tmp) - 1);
- else if (c->callerid)
+ else if (c->callerid && strlen(c->callerid))
strncpy(tmp, c->callerid, sizeof(tmp) - 1);
- if (c->callerid)
+ if (c->callerid && strlen(c->callerid))
strncpy(cdr->clid, c->callerid, sizeof(cdr->clid) - 1);
else
strcpy(cdr->clid, "");
diff --git a/channel.c b/channel.c
index 2ecde4fee..6d704d742 100755
--- a/channel.c
+++ b/channel.c
@@ -34,6 +34,7 @@
#include <asterisk/linkedlists.h>
#include <asterisk/indications.h>
#include <asterisk/monitor.h>
+#include <asterisk/causes.h>
#ifdef ZAPTEL_OPTIMIZATIONS
#include <sys/ioctl.h>
#include <linux/zaptel.h>
@@ -1493,8 +1494,7 @@ struct ast_channel *ast_request_and_dial(char *type, int format, void *data, int
int state = 0;
struct ast_channel *chan;
struct ast_frame *f;
- int res;
-
+ int res = 0;
chan = ast_request(type, format, data);
if (chan) {
if (callerid)
@@ -1504,8 +1504,6 @@ struct ast_channel *ast_request_and_dial(char *type, int format, void *data, int
res = ast_waitfor(chan, timeout);
if (res < 0) {
/* Something not cool, or timed out */
- ast_hangup(chan);
- chan = NULL;
break;
}
/* If done, break out */
@@ -1516,8 +1514,7 @@ struct ast_channel *ast_request_and_dial(char *type, int format, void *data, int
f = ast_read(chan);
if (!f) {
state = AST_CONTROL_HANGUP;
- ast_hangup(chan);
- chan = NULL;
+ res = 0;
break;
}
if (f->frametype == AST_FRAME_CONTROL) {
@@ -1537,17 +1534,36 @@ struct ast_channel *ast_request_and_dial(char *type, int format, void *data, int
}
ast_frfree(f);
}
- } else {
- ast_hangup(chan);
- chan = NULL;
+ } else
ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
- }
} else
ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
if (chan && (chan->_state == AST_STATE_UP))
state = AST_CONTROL_ANSWER;
if (outstate)
*outstate = state;
+ if (chan && res <= 0) {
+ if (!chan->cdr) {
+ chan->cdr = ast_cdr_alloc();
+ if (chan->cdr)
+ ast_cdr_init(chan->cdr, chan);
+ }
+ if (chan->cdr) {
+ char tmp[256];
+ sprintf(tmp, "%s/%s",type,(char *)data);
+ ast_cdr_setapp(chan->cdr,"Dial",tmp);
+ ast_cdr_update(chan);
+ ast_cdr_start(chan->cdr);
+ ast_cdr_end(chan->cdr);
+ /* If the cause wasn't handled properly */
+ if (ast_cdr_disposition(chan->cdr,chan->hangupcause))
+ ast_cdr_failed(chan->cdr);
+ ast_cdr_reset(chan->cdr,1);
+ } else
+ ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
+ ast_hangup(chan);
+ chan = NULL;
+ }
return chan;
}
@@ -2431,4 +2447,3 @@ int ast_tonepair(struct ast_channel *chan, int freq1, int freq2, int duration, i
return 0;
}
-
diff --git a/channels/chan_zap.c b/channels/chan_zap.c
index a0dded75b..284f70f43 100755
--- a/channels/chan_zap.c
+++ b/channels/chan_zap.c
@@ -36,6 +36,7 @@
#include <asterisk/dsp.h>
#include <asterisk/astdb.h>
#include <asterisk/manager.h>
+#include <asterisk/causes.h>
#include <sys/signal.h>
#include <sys/select.h>
#include <errno.h>
@@ -498,6 +499,23 @@ static int cidrings[] = {
#define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_SF)) /* || (p->sig & __ZT_SIG_FXO) */)
#define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_SF)) /* || (p->sig & __ZT_SIG_FXO) */)
+/* translate between PRI causes and asterisk's */
+int hangup_pri2cause(int cause)
+{
+ switch(cause) {
+#ifdef ZAPATA_PRI
+ case PRI_CAUSE_USER_BUSY:
+ return AST_CAUSE_BUSY;
+ case PRI_CAUSE_NORMAL_CLEARING:
+ return AST_CAUSE_NORMAL;
+#endif
+ default:
+ return AST_CAUSE_FAILURE;
+ }
+ /* never reached */
+ return 0;
+}
+
static int zt_get_index(struct ast_channel *ast, struct zt_pvt *p, int nullok)
{
int res;
@@ -6049,6 +6067,7 @@ static void *pri_dchannel(void *vpri)
if (chan) {
ast_mutex_lock(&pri->pvt[chan]->lock);
if (pri->pvt[chan]->owner) {
+ pri->pvt[chan]->owner->hangupcause = hangup_pri2cause(e->hangup.cause);
pri->pvt[chan]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Channel %d, span %d got hangup\n", chan, pri->span);
diff --git a/include/asterisk/cdr.h b/include/asterisk/cdr.h
index 0b9681035..3988832df 100755
--- a/include/asterisk/cdr.h
+++ b/include/asterisk/cdr.h
@@ -23,6 +23,7 @@
#define AST_CDR_NOANSWER (1 << 0)
#define AST_CDR_BUSY (1 << 1)
#define AST_CDR_ANSWERED (1 << 2)
+#define AST_CDR_FAILED (1 << 3)
//! AMA Flags
#define AST_CDR_OMIT (1)
@@ -142,6 +143,21 @@ extern void ast_cdr_answer(struct ast_cdr *cdr);
*/
extern void ast_cdr_busy(struct ast_cdr *cdr);
+//! Fail a call
+/*!
+ * \param cdr the cdr you wish to associate with the call
+ * Returns nothing important
+ */
+extern void ast_cdr_failed(struct ast_cdr *cdr);
+
+//! Save the result of the call based on the AST_CAUSE_*
+/*!
+ * \param cdr the cdr you wish to associate with the call
+ * Returns nothing important
+ * \param cause the AST_CAUSE_*
+ */
+extern int ast_cdr_disposition(struct ast_cdr *cdr, int cause);
+
//! End a call
/*!
* \param cdr the cdr you have associated the call with
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index 815f882f4..f33bb62d3 100755
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -213,6 +213,9 @@ struct ast_channel {
/* Unique Channel Identifier */
char uniqueid[32];
+ /* Why is the channel hanged up */
+ int hangupcause;
+
/* A linked list for variables */
struct ast_var_t *vars;
AST_LIST_HEAD(varshead,ast_var_t) varshead;
diff --git a/pbx.c b/pbx.c
index 5ad920948..8a7dd2fd7 100755
--- a/pbx.c
+++ b/pbx.c
@@ -3779,7 +3779,7 @@ static void *async_wait(void *data)
return NULL;
}
-int ast_pbx_outgoing_exten(char *type, int format, void *data, int timeout, char *context, char *exten, int priority, int *reason, int sync, char *callerid, char *variable )
+int ast_pbx_outgoing_exten(char *type, int format, void *data, int timeout, char *context, char *exten, int priority, int *reason, int sync, char *callerid, char *variable)
{
struct ast_channel *chan;
struct async_stat *as;
@@ -3828,6 +3828,27 @@ int ast_pbx_outgoing_exten(char *type, int format, void *data, int timeout, char
ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
ast_hangup(chan);
}
+ } else {
+ /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
+ /* check if "failed" exists */
+ if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
+ chan = ast_channel_alloc(0);
+ if (chan) {
+ strncpy(chan->name, "OutgoingSpoolFailed", sizeof(chan->name) - 1);
+ if (context && strlen(context))
+ strncpy(chan->context, context, sizeof(chan->context) - 1);
+ strncpy(chan->exten, "failed", sizeof(chan->exten) - 1);
+ chan->priority = 1;
+ /* JDG chanvar */
+ tmp = variable;
+ /* FIXME replace this call with strsep NOT*/
+ while( (var = strtok_r(NULL, "|", &tmp)) ) {
+ pbx_builtin_setvar( chan, var );
+ } /* /JDG */
+ ast_pbx_run(chan);
+ } else
+ ast_log(LOG_WARNING, "Can't allocate the channel structure, skipping execution of extension 'failed'\n");
+ }
}
} else {
as = malloc(sizeof(struct async_stat));