From 8a13712e45e41c4d413200e38a96898a4f1a79ab Mon Sep 17 00:00:00 2001 From: Mark Spencer Date: Tue, 26 Oct 2004 22:25:43 +0000 Subject: Pass concept of status back, permit "leaveempty" to work with static agents who are not loggedon (bug #2719) git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@4106 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- apps/app_chanisavail.c | 9 +++- apps/app_dial.c | 60 +++++++++++++++---------- apps/app_meetme.c | 2 +- apps/app_queue.c | 107 +++++++++++++++++++++++++++++++++++++++------ channel.c | 34 ++++++++++---- channels/chan_agent.c | 9 +++- channels/chan_alsa.c | 4 +- channels/chan_h323.c | 3 +- channels/chan_iax2.c | 5 ++- channels/chan_local.c | 2 +- channels/chan_mgcp.c | 5 ++- channels/chan_modem.c | 2 +- channels/chan_nbs.c | 2 +- channels/chan_oss.c | 4 +- channels/chan_phone.c | 6 ++- channels/chan_sip.c | 3 +- channels/chan_skinny.c | 2 +- channels/chan_vpb.c | 2 +- channels/chan_zap.c | 22 +++------- include/asterisk/causes.h | 2 + include/asterisk/channel.h | 6 +-- 21 files changed, 208 insertions(+), 83 deletions(-) diff --git a/apps/app_chanisavail.c b/apps/app_chanisavail.c index d61b0f1d3..91bf838b2 100755 --- a/apps/app_chanisavail.c +++ b/apps/app_chanisavail.c @@ -51,6 +51,7 @@ LOCAL_USER_DECL; static int chanavail_exec(struct ast_channel *chan, void *data) { int res=-1; + int status; struct localuser *u; char info[512], tmp[512], *peers, *tech, *number, *rest, *cur; struct ast_channel *tempchan; @@ -80,20 +81,24 @@ static int chanavail_exec(struct ast_channel *chan, void *data) } *number = '\0'; number++; - if ((tempchan = ast_request(tech, chan->nativeformats, number))) { + if ((tempchan = ast_request(tech, chan->nativeformats, number, &status))) { pbx_builtin_setvar_helper(chan, "AVAILCHAN", tempchan->name); /* Store the originally used channel too */ snprintf(tmp, sizeof(tmp), "%s/%s", tech, number); pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", tmp); + snprintf(tmp, sizeof(tmp), "%d", status); + pbx_builtin_setvar_helper(chan, "AVAILSTATUS", tmp); ast_hangup(tempchan); tempchan = NULL; res = 1; break; + } else { + snprintf(tmp, sizeof(tmp), "%d", status); + pbx_builtin_setvar_helper(chan, "AVAILSTATUS", tmp); } cur = rest; } while (cur); } - if (res < 1) { pbx_builtin_setvar_helper(chan, "AVAILCHAN", ""); pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", ""); diff --git a/apps/app_dial.c b/apps/app_dial.c index fddddebe9..0bf269a68 100755 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -134,14 +135,32 @@ static void hanguptree(struct localuser *outgoing, struct ast_channel *exception #define AST_MAX_WATCHERS 256 -static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, int *allowredir_in, int *allowredir_out, int *allowdisconnect_in, int *allowdisconnect_out, int *sentringing, char *status, size_t statussize) +#define HANDLE_CAUSE(blah, bleh) do { \ + switch(cause) { \ + case AST_CAUSE_BUSY: \ + if (bleh->cdr) \ + ast_cdr_busy(bleh->cdr); \ + numbusy++; \ + case AST_CAUSE_CONGESTION: \ + case AST_CAUSE_UNREGISTERED: \ + if (bleh->cdr) \ + ast_cdr_busy(bleh->cdr); \ + numcongestion++; \ + default: \ + numnochan++; \ + } \ +} while(0) + + +static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, int *allowredir_in, int *allowredir_out, int *allowdisconnect_in, int *allowdisconnect_out, int *sentringing, char *status, size_t statussize, int busystart, int nochanstart, int congestionstart) { struct localuser *o; int found; int numlines; - int numbusy = 0; - int numcongestion = 0; - int numnochan = 0; + int numbusy = busystart; + int numcongestion = congestionstart; + int numnochan = nochanstart; + int cause; int orig = *to; struct ast_frame *f; struct ast_channel *peer = NULL; @@ -227,11 +246,11 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name); /* Setup parameters */ - o->chan = ast_request(tech, in->nativeformats, stuff); + o->chan = ast_request(tech, in->nativeformats, stuff, &cause); if (!o->chan) { ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff); o->stillgoing = 0; - numnochan++; + HANDLE_CAUSE(cause, in); } else { if (o->chan->cid.cid_num) free(o->chan->cid.cid_num); @@ -317,9 +336,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu ast_hangup(o->chan); o->chan = NULL; o->stillgoing = 0; - if (in->cdr) - ast_cdr_busy(in->cdr); - numbusy++; + HANDLE_CAUSE(AST_CAUSE_BUSY, in); break; case AST_CONTROL_CONGESTION: if (option_verbose > 2) @@ -328,9 +345,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu ast_hangup(o->chan); o->chan = NULL; o->stillgoing = 0; - if (in->cdr) - ast_cdr_busy(in->cdr); - numcongestion++; + HANDLE_CAUSE(AST_CAUSE_CONGESTION, in); break; case AST_CONTROL_RINGING: if (option_verbose > 2) @@ -433,6 +448,10 @@ static int dial_exec(struct ast_channel *chan, void *data) int privacy=0; int announce=0; int resetcdr=0; + int numbusy = 0; + int numcongestion = 0; + int numnochan = 0; + int cause; char numsubst[AST_MAX_EXTENSION]; char restofit[AST_MAX_EXTENSION]; char *transfer = NULL; @@ -738,14 +757,11 @@ static int dial_exec(struct ast_channel *chan, void *data) ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst); } /* Request the peer */ - tmp->chan = ast_request(tech, chan->nativeformats, numsubst); + tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause); if (!tmp->chan) { /* If we can't, just go on to the next call */ ast_log(LOG_NOTICE, "Unable to create channel of type '%s'\n", tech); - if (chan->cdr) - ast_cdr_busy(chan->cdr); - free(tmp); - cur = rest; + HANDLE_CAUSE(cause, chan); continue; } if (!ast_strlen_zero(tmp->chan->call_forward)) { @@ -767,11 +783,10 @@ static int dial_exec(struct ast_channel *chan, void *data) ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' (thanks to %s)\n", chan->name, tech, stuff, tmp->chan->name); /* Setup parameters */ ast_hangup(tmp->chan); - tmp->chan = ast_request(tech, chan->nativeformats, stuff); + tmp->chan = ast_request(tech, chan->nativeformats, stuff, &cause); if (!tmp->chan) { ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff); - free(tmp); - cur = rest; + HANDLE_CAUSE(cause, chan); continue; } } @@ -847,8 +862,7 @@ static int dial_exec(struct ast_channel *chan, void *data) else if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst); ast_hangup(tmp->chan); - free(tmp); - cur = rest; + tmp->chan = NULL; continue; } else if (option_verbose > 2) @@ -888,7 +902,7 @@ static int dial_exec(struct ast_channel *chan, void *data) strncpy(status, "CHANUNAVAIL", sizeof(status) - 1); time(&start_time); - peer = wait_for_answer(chan, outgoing, &to, &allowredir_in, &allowredir_out, &allowdisconnect_in, &allowdisconnect_out, &sentringing, status, sizeof(status)); + peer = wait_for_answer(chan, outgoing, &to, &allowredir_in, &allowredir_out, &allowdisconnect_in, &allowdisconnect_out, &sentringing, status, sizeof(status), numbusy, numnochan, numcongestion); if (!peer) { if (to) diff --git a/apps/app_meetme.c b/apps/app_meetme.c index e853dc87e..064e52c78 100755 --- a/apps/app_meetme.c +++ b/apps/app_meetme.c @@ -222,7 +222,7 @@ static struct ast_conference *build_conf(char *confno, char *pin, int make, int strncpy(cnf->confno, confno, sizeof(cnf->confno) - 1); strncpy(cnf->pin, pin, sizeof(cnf->pin) - 1); cnf->markedusers = 0; - cnf->chan = ast_request("zap", AST_FORMAT_ULAW, "pseudo"); + cnf->chan = ast_request("zap", AST_FORMAT_ULAW, "pseudo", NULL); if (cnf->chan) { cnf->fd = cnf->chan->fds[0]; /* for use by conf_play() */ } else { diff --git a/apps/app_queue.c b/apps/app_queue.c index 0febe5622..f0fbbbbfc 100755 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -145,6 +146,7 @@ struct localuser { char tech[40]; int stillgoing; int metric; + int oldstatus; int allowredirect_in; int allowredirect_out; int ringbackonly; @@ -182,6 +184,7 @@ struct member { int penalty; /* Are we a last resort? */ int calls; /* Number of calls serviced by this member */ int dynamic; /* Are we dynamically added? */ + int status; /* Status of queue member */ time_t lastcall; /* When last successful call was hungup */ struct member *next; /* Next member */ }; @@ -280,6 +283,26 @@ static inline void insert_entry(struct ast_call_queue *q, new->opos = *pos; } +static int has_no_members(struct ast_call_queue *q) +{ + struct member *member; + int empty = 1; + member = q->members; + while(empty && member) { + switch(member->status) { + case AST_CAUSE_NOSUCHDRIVER: + case AST_CAUSE_UNREGISTERED: + /* Not logged on, etc */ + break; + default: + /* Not empty */ + empty = 0; + } + member = member->next; + } + return empty; +} + static int join_queue(char *queuename, struct queue_ent *qe) { struct ast_call_queue *q; @@ -293,7 +316,7 @@ static int join_queue(char *queuename, struct queue_ent *qe) if (!strcasecmp(q->name, queuename)) { /* This is our one */ ast_mutex_lock(&q->lock); - if ((q->members || q->joinempty) && (!q->maxlen || (q->count < q->maxlen))) { + if ((!has_no_members(q) || q->joinempty || !q->head) && (!q->maxlen || (q->count < q->maxlen))) { /* There's space for us, put us at the right position inside * the queue. * Take into account the priority of the calling user */ @@ -551,9 +574,29 @@ static void hanguptree(struct localuser *outgoing, struct ast_channel *exception } } +static int update_status(struct ast_call_queue *q, struct member *member, int status) +{ + struct member *cur; + /* Since a reload could have taken place, we have to traverse the list to + be sure it's still valid */ + ast_mutex_lock(&q->lock); + cur = q->members; + while(cur) { + if (member == cur) { + cur->status = status; + break; + } + cur = cur->next; + } + q->callscompleted++; + ast_mutex_unlock(&q->lock); + return 0; +} + static int ring_entry(struct queue_ent *qe, struct localuser *tmp) { int res; + int status; if (qe->parent->wrapuptime && (time(NULL) - tmp->lastcall < qe->parent->wrapuptime)) { ast_log(LOG_DEBUG, "Wrapuptime not yet expired for %s/%s\n", tmp->tech, tmp->numsubst); if (qe->chan->cdr) @@ -562,7 +605,7 @@ static int ring_entry(struct queue_ent *qe, struct localuser *tmp) return 0; } /* Request the peer */ - tmp->chan = ast_request(tmp->tech, qe->chan->nativeformats, tmp->numsubst); + tmp->chan = ast_request(tmp->tech, qe->chan->nativeformats, tmp->numsubst, &status); if (!tmp->chan) { /* If we can't, just go on to the next call */ #if 0 ast_log(LOG_NOTICE, "Unable to create channel of type '%s'\n", cur->tech); @@ -570,8 +613,11 @@ static int ring_entry(struct queue_ent *qe, struct localuser *tmp) if (qe->chan->cdr) ast_cdr_busy(qe->chan->cdr); tmp->stillgoing = 0; + update_status(qe->parent, tmp->member, status); return 0; - } + } else if (status != tmp->oldstatus) + update_status(qe->parent, tmp->member, status); + tmp->chan->appl = "AppQueue"; tmp->chan->data = "(Outgoing Line)"; tmp->chan->whentohangup = 0; @@ -728,6 +774,7 @@ static struct localuser *wait_for_answer(struct queue_ent *qe, struct localuser struct localuser *o; int found; int numlines; + int status; int sentringing = 0; int numbusies = 0; int numnochan = 0; @@ -795,7 +842,9 @@ static struct localuser *wait_for_answer(struct queue_ent *qe, struct localuser if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name); /* Setup parameters */ - o->chan = ast_request(tech, in->nativeformats, stuff); + o->chan = ast_request(tech, in->nativeformats, stuff, &status); + if (status != o->oldstatus) + update_status(qe->parent, o->member, status); if (!o->chan) { ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff); o->stillgoing = 0; @@ -997,7 +1046,7 @@ static int wait_our_turn(struct queue_ent *qe, int ringing) } /* leave the queue if no agents, if enabled */ - if (!(qe->parent->members) && qe->parent->leavewhenempty) { + if (has_no_members(qe->parent) && qe->parent->leavewhenempty) { leave_queue(qe); break; } @@ -1163,6 +1212,7 @@ static int try_calling(struct queue_ent *qe, char *options, char *announceoverri tmp->member = cur; /* Never directly dereference! Could change on reload */ strncpy(tmp->tech, cur->tech, sizeof(tmp->tech)-1); strncpy(tmp->numsubst, cur->loc, sizeof(tmp->numsubst)-1); + tmp->oldstatus = cur->status; tmp->lastcall = cur->lastcall; /* If we're dialing by extension, look at the extension to know what to dial */ if ((newnum = strstr(tmp->numsubst, "BYEXTENSION"))) { @@ -1728,6 +1778,7 @@ check_turns: } } if (!res) { + int makeannouncement = 0; for (;;) { /* This is the wait loop for the head caller*/ /* To exit, they may get their call answered; */ @@ -1740,15 +1791,12 @@ check_turns: break; } - /* leave the queue if no agents, if enabled */ - if (!((qe.parent)->members) && (qe.parent)->leavewhenempty) { - leave_queue(&qe); - break; + if (makeannouncement) { + /* Make a position announcement, if enabled */ + if (qe.parent->announcefrequency && !ringing) + say_position(&qe); } - - /* Make a position announcement, if enabled */ - if (qe.parent->announcefrequency && !ringing) - say_position(&qe); + makeannouncement = 1; /* Try calling all queue members for 'timeout' seconds */ res = try_calling(&qe, options, announceoverride, url, &go_on); @@ -1761,6 +1809,12 @@ check_turns: break; } + /* leave the queue if no agents, if enabled */ + if (has_no_members(qe.parent) && (qe.parent->leavewhenempty)) { + res = 0; + break; + } + /* Leave if we have exceeded our queuetimeout */ if (qe.queuetimeout && ( (time(NULL) - qe.start) >= qe.queuetimeout) ) { res = 0; @@ -2037,6 +2091,30 @@ static void reload_queues(void) ast_mutex_unlock(&qlock); } +static char *status2str(int status, char *buf, int buflen) +{ + switch(status) { + case AST_CAUSE_BUSY: + strncpy(buf, "busy", buflen - 1); + break; + case AST_CAUSE_CONGESTION: + strncpy(buf, "congestion", buflen - 1); + break; + case AST_CAUSE_FAILURE: + strncpy(buf, "failure", buflen - 1); + break; + case AST_CAUSE_UNREGISTERED: + strncpy(buf, "unregistered", buflen - 1); + break; + case AST_CAUSE_NOSUCHDRIVER: + strncpy(buf, "nosuchdriver", buflen - 1); + break; + default: + snprintf(buf, buflen, "unknown status %d", status); + } + return buf; +} + static int __queues_show(int fd, int argc, char **argv, int queue_show) { struct ast_call_queue *q; @@ -2046,6 +2124,7 @@ static int __queues_show(int fd, int argc, char **argv, int queue_show) time_t now; char max[80] = ""; char calls[80] = ""; + char tmpbuf[80] = ""; float sl = 0; time(&now); @@ -2092,6 +2171,8 @@ static int __queues_show(int fd, int argc, char **argv, int queue_show) max[0] = '\0'; if (mem->dynamic) strncat(max, " (dynamic)", sizeof(max) - strlen(max) - 1); + if (mem->status) + snprintf(max + strlen(max), sizeof(max) - strlen(max), " (%s)", status2str(mem->status, tmpbuf, sizeof(tmpbuf))); if (mem->calls) { snprintf(calls, sizeof(calls), " has taken %d calls (last was %ld secs ago)", mem->calls, (long)(time(NULL) - mem->lastcall)); diff --git a/channel.c b/channel.c index b9607a03e..9ef5c9015 100755 --- a/channel.c +++ b/channel.c @@ -65,7 +65,7 @@ struct chanlist { char type[80]; char description[80]; int capabilities; - struct ast_channel * (*requester)(const char *type, int format, void *data); + struct ast_channel * (*requester)(const char *type, int format, void *data, int *cause); int (*devicestate)(void *data); struct chanlist *next; } *backends = NULL; @@ -154,13 +154,13 @@ void ast_channel_setwhentohangup(struct ast_channel *chan, time_t offset) } int ast_channel_register(const char *type, const char *description, int capabilities, - struct ast_channel *(*requester)(const char *type, int format, void *data)) + struct ast_channel *(*requester)(const char *type, int format, void *data, int *cause)) { return ast_channel_register_ex(type, description, capabilities, requester, NULL); } int ast_channel_register_ex(const char *type, const char *description, int capabilities, - struct ast_channel *(*requester)(const char *type, int format, void *data), + struct ast_channel *(*requester)(const char *type, int format, void *data, int *cause), int (*devicestate)(void *data)) { struct chanlist *chan, *last=NULL; @@ -1751,11 +1751,12 @@ int ast_set_read_format(struct ast_channel *chan, int fmts) struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, struct outgoing_helper *oh) { int state = 0; + int cause = 0; struct ast_channel *chan; struct ast_frame *f; int res = 0; char *variable; - chan = ast_request(type, format, data); + chan = ast_request(type, format, data, &cause); if (chan) { if (oh) { char *tmp, *var; @@ -1815,9 +1816,18 @@ struct ast_channel *__ast_request_and_dial(const char *type, int format, void *d ast_frfree(f); } } else - ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data); - } else + ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data); + } else { ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data); + switch(cause) { + case AST_CAUSE_BUSY: + state = AST_CONTROL_BUSY; + break; + case AST_CAUSE_CONGESTION: + state = AST_CONTROL_CONGESTION; + break; + } + } if (chan) { /* Final fixups */ if (oh) { @@ -1861,13 +1871,17 @@ struct ast_channel *ast_request_and_dial(const char *type, int format, void *dat return __ast_request_and_dial(type, format, data, timeout, outstate, cidnum, cidname, NULL); } -struct ast_channel *ast_request(const char *type, int format, void *data) +struct ast_channel *ast_request(const char *type, int format, void *data, int *cause) { struct chanlist *chan; struct ast_channel *c = NULL; int capabilities; int fmt; int res; + int foo; + if (!cause) + cause = &foo; + *cause = AST_CAUSE_NOTDEFINED; if (ast_mutex_lock(&chlock)) { ast_log(LOG_WARNING, "Unable to lock channel list\n"); return NULL; @@ -1885,7 +1899,7 @@ struct ast_channel *ast_request(const char *type, int format, void *data) } ast_mutex_unlock(&chlock); if (chan->requester) - c = chan->requester(type, capabilities, data); + c = chan->requester(type, capabilities, data, cause); if (c) { if (c->_state == AST_STATE_DOWN) { manager_event(EVENT_FLAG_CALL, "Newchannel", @@ -1901,8 +1915,10 @@ struct ast_channel *ast_request(const char *type, int format, void *data) } chan = chan->next; } - if (!chan) + if (!chan) { ast_log(LOG_WARNING, "No channel type registered for '%s'\n", type); + *cause = AST_CAUSE_NOSUCHDRIVER; + } ast_mutex_unlock(&chlock); return c; } diff --git a/channels/chan_agent.c b/channels/chan_agent.c index d16677c7d..8e596a44f 100755 --- a/channels/chan_agent.c +++ b/channels/chan_agent.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -1051,7 +1052,7 @@ static int check_beep(struct agent_pvt *newlyavailable, int needlock) return res; } -static struct ast_channel *agent_request(const char *type, int format, void *data) +static struct ast_channel *agent_request(const char *type, int format, void *data, int *cause) { struct agent_pvt *p; struct ast_channel *chan = NULL; @@ -1113,7 +1114,7 @@ static struct ast_channel *agent_request(const char *type, int format, void *dat chan = agent_new(p, AST_STATE_DOWN); } else if (!p->owner && !ast_strlen_zero(p->loginchan)) { /* Adjustable agent */ - p->chan = ast_request("Local", format, p->loginchan); + p->chan = ast_request("Local", format, p->loginchan, cause); if (p->chan) chan = agent_new(p, AST_STATE_DOWN); } @@ -1142,6 +1143,10 @@ static struct ast_channel *agent_request(const char *type, int format, void *dat } else ast_log(LOG_DEBUG, "Not creating place holder for '%s' since nobody logged in\n", s); } + if (hasagent) + *cause = AST_CAUSE_BUSY; + else + *cause = AST_CAUSE_UNREGISTERED; ast_mutex_unlock(&agentlock); return chan; } diff --git a/channels/chan_alsa.c b/channels/chan_alsa.c index 09074ec87..e00eecd44 100755 --- a/channels/chan_alsa.c +++ b/channels/chan_alsa.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -753,7 +754,7 @@ static struct ast_channel *alsa_new(struct chan_alsa_pvt *p, int state) return tmp; } -static struct ast_channel *alsa_request(const char *type, int format, void *data) +static struct ast_channel *alsa_request(const char *type, int format, void *data, int *cause) { int oldformat = format; struct ast_channel *tmp=NULL; @@ -765,6 +766,7 @@ static struct ast_channel *alsa_request(const char *type, int format, void *data ast_mutex_lock(&alsalock); if (alsa.owner) { ast_log(LOG_NOTICE, "Already have a call on the ALSA channel\n"); + *cause = AST_CAUSE_BUSY; } else { tmp= alsa_new(&alsa, AST_STATE_DOWN); if (!tmp) { diff --git a/channels/chan_h323.c b/channels/chan_h323.c index a405567cb..8965fc125 100755 --- a/channels/chan_h323.c +++ b/channels/chan_h323.c @@ -66,6 +66,7 @@ extern "C" { #include #include #include +#include #ifdef __cplusplus } #endif @@ -948,7 +949,7 @@ static int create_addr(struct oh323_pvt *pvt, char *opeer) return 0; } } -static struct ast_channel *oh323_request(const char *type, int format, void *data) +static struct ast_channel *oh323_request(const char *type, int format, void *data, int *cause) { int oldformat; struct oh323_pvt *pvt; diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index ed87ad994..733490e09 100755 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -6208,7 +6209,7 @@ static void free_context(struct iax2_context *con) } } -static struct ast_channel *iax2_request(const char *type, int format, void *data) +static struct ast_channel *iax2_request(const char *type, int format, void *data, int *cause) { int callno; int res; @@ -6248,6 +6249,7 @@ static struct ast_channel *iax2_request(const char *type, int format, void *data /* Populate our address from the given */ if (create_addr(&sin, &capability, &sendani, &maxtime, hostname, NULL, &trunk, ¬ransfer, &usejitterbuf, NULL, 0, NULL, 0, &found, NULL)) { + *cause = AST_CAUSE_UNREGISTERED; return NULL; } if (portno) { @@ -6256,6 +6258,7 @@ static struct ast_channel *iax2_request(const char *type, int format, void *data callno = find_callno(0, 0, &sin, NEW_FORCE, 1); if (callno < 1) { ast_log(LOG_WARNING, "Unable to create call\n"); + *cause = AST_CAUSE_CONGESTION; return NULL; } ast_mutex_lock(&iaxsl[callno]); diff --git a/channels/chan_local.c b/channels/chan_local.c index 8b2c5be54..661ab403e 100755 --- a/channels/chan_local.c +++ b/channels/chan_local.c @@ -462,7 +462,7 @@ static struct ast_channel *local_new(struct local_pvt *p, int state) } -static struct ast_channel *local_request(const char *type, int format, void *data) +static struct ast_channel *local_request(const char *type, int format, void *data, int *cause) { struct local_pvt *p; struct ast_channel *chan = NULL; diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c index a66fb6d8d..0b1fafd83 100755 --- a/channels/chan_mgcp.c +++ b/channels/chan_mgcp.c @@ -72,6 +72,7 @@ #include #include #include +#include #include #include #include @@ -3342,7 +3343,7 @@ static int restart_monitor(void) return 0; } -static struct ast_channel *mgcp_request(const char *type, int format, void *data) +static struct ast_channel *mgcp_request(const char *type, int format, void *data, int *cause) { int oldformat; struct mgcp_subchannel *sub; @@ -3364,6 +3365,7 @@ static struct ast_channel *mgcp_request(const char *type, int format, void *data sub = find_subchannel(tmp, 0, NULL); if (!sub) { ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp); + *cause = AST_CAUSE_UNREGISTERED; return NULL; } @@ -3383,6 +3385,7 @@ static struct ast_channel *mgcp_request(const char *type, int format, void *data transmit_notify_request(sub,"L/vmwi(-)"); } } + *cause = AST_CAUSE_BUSY; return NULL; } tmpc = mgcp_new(sub->owner ? sub->next : sub, AST_STATE_DOWN); diff --git a/channels/chan_modem.c b/channels/chan_modem.c index c6a27f1a4..41d95540b 100755 --- a/channels/chan_modem.c +++ b/channels/chan_modem.c @@ -773,7 +773,7 @@ static struct ast_modem_pvt *mkif(char *iface) return tmp; } -static struct ast_channel *modem_request(const char *type, int format, void *data) +static struct ast_channel *modem_request(const char *type, int format, void *data, int *cause) { int oldformat; struct ast_modem_pvt *p; diff --git a/channels/chan_nbs.c b/channels/chan_nbs.c index 6f67b3ada..b3fdfbf93 100755 --- a/channels/chan_nbs.c +++ b/channels/chan_nbs.c @@ -232,7 +232,7 @@ static struct ast_channel *nbs_new(struct nbs_pvt *i, int state) } -static struct ast_channel *nbs_request(const char *type, int format, void *data) +static struct ast_channel *nbs_request(const char *type, int format, void *data, int *cause) { int oldformat; struct nbs_pvt *p; diff --git a/channels/chan_oss.c b/channels/chan_oss.c index c1d5ee0b3..ad87a9128 100755 --- a/channels/chan_oss.c +++ b/channels/chan_oss.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -745,7 +746,7 @@ static struct ast_channel *oss_new(struct chan_oss_pvt *p, int state) return tmp; } -static struct ast_channel *oss_request(const char *type, int format, void *data) +static struct ast_channel *oss_request(const char *type, int format, void *data, int *cause) { int oldformat = format; struct ast_channel *tmp; @@ -756,6 +757,7 @@ static struct ast_channel *oss_request(const char *type, int format, void *data) } if (oss.owner) { ast_log(LOG_NOTICE, "Already have a call on the OSS channel\n"); + *cause = AST_CAUSE_BUSY; return NULL; } tmp= oss_new(&oss, AST_STATE_DOWN); diff --git a/channels/chan_phone.c b/channels/chan_phone.c index b91b3657f..b81c5b04d 100755 --- a/channels/chan_phone.c +++ b/channels/chan_phone.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -1023,7 +1024,7 @@ static struct phone_pvt *mkif(char *iface, int mode, int txgain, int rxgain) return tmp; } -static struct ast_channel *phone_request(const char *type, int format, void *data) +static struct ast_channel *phone_request(const char *type, int format, void *data, int *cause) { int oldformat; struct phone_pvt *p; @@ -1047,7 +1048,8 @@ static struct ast_channel *phone_request(const char *type, int format, void *dat if (!p->owner) { tmp = phone_new(p, AST_STATE_DOWN, p->context); break; - } + } else + *cause = AST_CAUSE_BUSY; } p = p->next; } diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 56acb1683..2181c6d87 100755 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -7946,7 +7946,7 @@ static int sip_devicestate(void *data) /*--- sip_request: PBX interface function -build SIP pvt structure ---*/ /* SIP calls initiated by the PBX arrive here */ -static struct ast_channel *sip_request(const char *type, int format, void *data) +static struct ast_channel *sip_request(const char *type, int format, void *data, int *cause) { int oldformat; struct sip_pvt *p; @@ -7990,6 +7990,7 @@ static struct ast_channel *sip_request(const char *type, int format, void *data) p->capability = global_capability; if (create_addr(p, host)) { + *cause = AST_CAUSE_UNREGISTERED; sip_destroy(p); return NULL; } diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c index a77c4b18f..dbf27977b 100755 --- a/channels/chan_skinny.c +++ b/channels/chan_skinny.c @@ -2489,7 +2489,7 @@ static int restart_monitor(void) return 0; } -static struct ast_channel *skinny_request(const char *type, int format, void *data) +static struct ast_channel *skinny_request(const char *type, int format, void *data, int *cause) { int oldformat; struct skinny_subchannel *sub; diff --git a/channels/chan_vpb.c b/channels/chan_vpb.c index 617367f95..82044e77c 100755 --- a/channels/chan_vpb.c +++ b/channels/chan_vpb.c @@ -2115,7 +2115,7 @@ static struct ast_channel *vpb_new(struct vpb_pvt *me, int state, char *context) return tmp; } -static struct ast_channel *vpb_request(const char *type, int format, void *data) +static struct ast_channel *vpb_request(const char *type, int format, void *data, int *cause) { int oldformat; struct vpb_pvt *p; diff --git a/channels/chan_zap.c b/channels/chan_zap.c index 07fe9ca51..1590252cd 100755 --- a/channels/chan_zap.c +++ b/channels/chan_zap.c @@ -6732,7 +6732,7 @@ static int pri_find_empty_chan(struct zt_pri *pri, int backwards) } #endif -static struct ast_channel *zt_request(const char *type, int format, void *data) +static struct ast_channel *zt_request(const char *type, int format, void *data, int *cause) { int oldformat; int groupmatch = 0; @@ -6945,21 +6945,8 @@ next: } ast_mutex_unlock(lock); restart_monitor(); - if (!tmp) { - if (busy && (channelmatch != CHAN_PSEUDO)) { - tmp = zt_request("Zap", format, "pseudo"); - if (tmp) { - char newname[80]; - ast_mutex_lock(&tmp->lock); - snprintf(newname, sizeof(newname), "Zap/%s-busy-%d", (char *)data, rand()); - ast_change_name(tmp, newname); - ast_setstate(tmp, AST_STATE_BUSY); - ast_mutex_unlock(&tmp->lock); - } - } else if (busy) { - ast_log(LOG_WARNING, "Whoa, the pseudo was busy somehow!\n"); - } - } + if (callwait || (!tmp && busy)) + *cause = AST_CAUSE_BUSY; return tmp; } @@ -7200,6 +7187,7 @@ static void *pri_dchannel(void *vpri) time_t t; int i, which=-1; int numdchans; + int cause=0; struct zt_pvt *crv; pthread_t threadid; pthread_attr_t attr; @@ -7277,7 +7265,7 @@ static void *pri_dchannel(void *vpri) (tv.tv_usec - lastidle.tv_usec) / 1000) > 1000) { /* Don't create a new idle call more than once per second */ snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial); - idle = zt_request("Zap", AST_FORMAT_ULAW, idlen); + idle = zt_request("Zap", AST_FORMAT_ULAW, idlen, &cause); if (idle) { pri->pvts[nextidle]->isidlecall = 1; if (ast_pthread_create(&p, NULL, do_idle_thread, idle)) { diff --git a/include/asterisk/causes.h b/include/asterisk/causes.h index 6a6c5dc8d..684f3d72c 100755 --- a/include/asterisk/causes.h +++ b/include/asterisk/causes.h @@ -66,6 +66,8 @@ #define AST_CAUSE_NORMAL AST_CAUSE_NORMAL_CLEARING #define AST_CAUSE_NOANSWER AST_CAUSE_NO_ANSWER #define AST_CAUSE_CONGESTION AST_CAUSE_NORMAL_CIRCUIT_CONGESTION +#define AST_CAUSE_UNREGISTERED AST_CAUSE_NO_ROUTE_DESTINATION #define AST_CAUSE_NOTDEFINED 0 +#define AST_CAUSE_NOSUCHDRIVER AST_CAUSE_CHAN_NOT_IMPLEMENTED #endif diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index f56f5bba0..6b514befe 100755 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -377,7 +377,7 @@ struct outgoing_helper { * by the low level module * Returns an ast_channel on success, NULL on failure. */ -struct ast_channel *ast_request(const char *type, int format, void *data); +struct ast_channel *ast_request(const char *type, int format, void *data, int *status); //! Search the Channels by Name /*! @@ -427,11 +427,11 @@ struct ast_channel *__ast_request_and_dial(const char *type, int format, void *d * Returns 0 on success, -1 on failure. */ int ast_channel_register(const char *type, const char *description, int capabilities, - struct ast_channel* (*requester)(const char *type, int format, void *data)); + struct ast_channel* (*requester)(const char *type, int format, void *data, int *cause)); /* Same like the upper function but with support for devicestate */ int ast_channel_register_ex(const char *type, const char *description, int capabilities, - struct ast_channel *(*requester)(const char *type, int format, void *data), + struct ast_channel *(*requester)(const char *type, int format, void *data, int *cause), int (*devicestate)(void *data)); //! Unregister a channel class -- cgit v1.2.3