diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/app_dial.c | 148 | ||||
-rw-r--r-- | apps/app_queue.c | 52 |
2 files changed, 128 insertions, 72 deletions
diff --git a/apps/app_dial.c b/apps/app_dial.c index 73d2d4c15..56a4336af 100644 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -61,6 +61,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/manager.h" #include "asterisk/privacy.h" #include "asterisk/stringfields.h" +#include "asterisk/global_datastores.h" static char *app = "Dial"; @@ -303,7 +304,6 @@ AST_APP_OPTIONS(dial_exec_options, { struct dial_localuser { struct ast_channel *chan; unsigned int flags; - int forwards; struct dial_localuser *next; }; @@ -322,8 +322,6 @@ static void hanguptree(struct dial_localuser *outgoing, struct ast_channel *exce } } -#define AST_MAX_FORWARDS 8 - #define AST_MAX_WATCHERS 256 #define HANDLE_CAUSE(cause, chan) do { \ @@ -488,30 +486,23 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct dial_l tech = "Local"; } /* Before processing channel, go ahead and check for forwarding */ - o->forwards++; - if (o->forwards < AST_MAX_FORWARDS) { - if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, c->name); - /* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */ - if (ast_test_flag(peerflags, OPT_IGNORE_FORWARDING)) { - if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' prevented.\n", in->name, tech, stuff); - c = o->chan = NULL; - cause = AST_CAUSE_BUSY; - } else { - /* Setup parameters */ - if ((c = o->chan = ast_request(tech, in->nativeformats, stuff, &cause))) { - if (single) - ast_channel_make_compatible(o->chan, in); - ast_channel_inherit_variables(in, o->chan); - } else - ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause); - } - } else { + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, c->name); + /* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */ + if (ast_test_flag(peerflags, OPT_IGNORE_FORWARDING)) { if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", c->name); - cause = AST_CAUSE_CONGESTION; + ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' prevented.\n", in->name, tech, stuff); c = o->chan = NULL; + cause = AST_CAUSE_BUSY; + } else { + /* Setup parameters */ + if ((c = o->chan = ast_request(tech, in->nativeformats, stuff, &cause))) { + if (single) + ast_channel_make_compatible(o->chan, in); + ast_channel_inherit_variables(in, o->chan); + ast_channel_datastore_inherit(in, o->chan); + } else + ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause); } if (!c) { ast_clear_flag(o, DIAL_STILLGOING); @@ -847,6 +838,8 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags ); struct ast_flags opts = { 0, }; char *opt_args[OPT_ARG_ARRAY_SIZE]; + struct ast_datastore *datastore; + int fulldial = 0, num_dialed = 0; if (ast_strlen_zero(data)) { ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n"); @@ -1107,7 +1100,13 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags struct dial_localuser *tmp; /* Get a technology/[device:]number pair */ char *number = cur; + char *interface = ast_strdupa(number); char *tech = strsep(&number, "/"); + /* find if we already dialed this interface */ + int dialed = 0; + struct ast_dialed_interface *di; + AST_LIST_HEAD(, ast_dialed_interface) *dialed_interfaces; + num_dialed++; if (!number) { ast_log(LOG_WARNING, "Dial argument takes format (technology/[device:]number1)\n"); goto out; @@ -1125,6 +1124,50 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags } ast_copy_string(numsubst, number, sizeof(numsubst)); /* Request the peer */ + if (!(datastore = ast_channel_datastore_find(chan, &dialed_interface_info, NULL))) { + if(!(datastore = ast_channel_datastore_alloc(&dialed_interface_info, NULL))) { + ast_log(LOG_WARNING, "Unable to create channel datastore for dialed interfaces. Aborting!\n"); + free(tmp); + goto out; + } + else { + datastore->inheritance = DATASTORE_INHERIT_FOREVER; + if((dialed_interfaces = ast_calloc(1, sizeof(*dialed_interfaces)))) { + datastore->data = dialed_interfaces; + AST_LIST_HEAD_INIT(dialed_interfaces); + ast_channel_datastore_add(chan, datastore); + } else { + free(tmp); + goto out; + } + } + } else + dialed_interfaces = datastore->data; + AST_LIST_LOCK(dialed_interfaces); + AST_LIST_TRAVERSE(dialed_interfaces, di, list) { + /* XXX case sensitive??? */ + if(!strcasecmp(di->interface, interface)) { + dialed = 1; + break; + } + } + if(!dialed && strcasecmp(tech, "Local")) { + if(!(di = ast_calloc(1, sizeof(*di) + strlen(interface)))) { + AST_LIST_UNLOCK(dialed_interfaces); + free(tmp); + goto out; + } + strcpy(di->interface, interface); + AST_LIST_INSERT_TAIL(dialed_interfaces, di, list); + } else { + AST_LIST_UNLOCK(dialed_interfaces); + ast_log(LOG_WARNING, "Skipping dialing interface '%s' again since it has already been dialed\n", di->interface); + fulldial++; + free(tmp); + continue; + } + AST_LIST_UNLOCK(dialed_interfaces); + tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause); if (!tmp->chan) { /* If we can't, just go on to the next call */ @@ -1135,51 +1178,8 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags free(tmp); continue; } - pbx_builtin_setvar_helper(tmp->chan, "DIALEDPEERNUMBER", numsubst); - if (!ast_strlen_zero(tmp->chan->call_forward)) { - char tmpchan[256]; - char *stuff; - char *tech; - ast_copy_string(tmpchan, tmp->chan->call_forward, sizeof(tmpchan)); - if ((stuff = strchr(tmpchan, '/'))) { - *stuff++ = '\0'; - tech = tmpchan; - } else { - snprintf(tmpchan, sizeof(tmpchan), "%s@%s", tmp->chan->call_forward, tmp->chan->context); - stuff = tmpchan; - tech = "Local"; - } - tmp->forwards++; - if (tmp->forwards < AST_MAX_FORWARDS) { - if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", chan->name, tech, stuff, tmp->chan->name); - ast_hangup(tmp->chan); - /* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */ - if (ast_test_flag(&opts, OPT_IGNORE_FORWARDING)) { - tmp->chan = NULL; - cause = AST_CAUSE_BUSY; - if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' prevented.\n", chan->name, tech, stuff); - } else { - 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' (cause = %d)\n", tech, stuff, cause); - else - ast_channel_inherit_variables(chan, tmp->chan); - } else { - if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", tmp->chan->name); - ast_hangup(tmp->chan); - tmp->chan = NULL; - cause = AST_CAUSE_CONGESTION; - } - if (!tmp->chan) { - HANDLE_CAUSE(cause, chan); - free(tmp); - continue; - } - } + + pbx_builtin_setvar_helper(tmp->chan, "DIALEDPEERNUMBER", numsubst); /* Setup outgoing SDP to match incoming one */ ast_rtp_make_compatible(tmp->chan, chan, !outgoing && !rest); @@ -1284,6 +1284,10 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags if (!outgoing) { strcpy(status, "CHANUNAVAIL"); + if(fulldial == num_dialed) { + res = -1; + goto out; + } } else { /* Our status will at least be NOANSWER */ strcpy(status, "NOANSWER"); @@ -1306,7 +1310,9 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags time(&start_time); peer = wait_for_answer(chan, outgoing, &to, peerflags, &sentringing, status, sizeof(status), numbusy, numnochan, numcongestion, ast_test_flag(&opts, OPT_PRIORITY_JUMP), &result); - + + ast_channel_datastore_remove(chan, datastore); + ast_channel_datastore_free(datastore); if (!peer) { if (result) { res = result; diff --git a/apps/app_queue.c b/apps/app_queue.c index db4a574ba..842998d9e 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -93,6 +93,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/devicestate.h" #include "asterisk/stringfields.h" #include "asterisk/astobj2.h" +#include "asterisk/global_datastores.h" enum { QUEUE_STRATEGY_RINGALL = 0, @@ -2133,6 +2134,7 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte numnochan++; } else { ast_channel_inherit_variables(in, o->chan); + ast_channel_datastore_inherit(in, o->chan); if (o->chan->cid.cid_num) free(o->chan->cid.cid_num); o->chan->cid.cid_num = ast_strdup(in->cid.cid_num); @@ -2500,6 +2502,7 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce int forwardsallowed = 1; int callcompletedinsl; struct ao2_iterator memi; + struct ast_datastore *datastore = ast_channel_datastore_find(qe->chan, &dialed_interface_info, NULL); memset(&bridge_config, 0, sizeof(bridge_config)); time(&now); @@ -2555,7 +2558,9 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce memi = ao2_iterator_init(qe->parent->members, 0); while ((cur = ao2_iterator_next(&memi))) { struct callattempt *tmp = ast_calloc(1, sizeof(*tmp)); - + struct ast_dialed_interface *di; + int dialed = 0; + AST_LIST_HEAD(, ast_dialed_interface) *dialed_interfaces; if (!tmp) { ao2_ref(cur, -1); ast_mutex_unlock(&qe->parent->lock); @@ -2563,6 +2568,49 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce AST_LIST_UNLOCK(&queues); goto out; } + if (!datastore) { + if(!(datastore = ast_channel_datastore_alloc(&dialed_interface_info, NULL))) { + ao2_ref(cur, -1); + ast_mutex_unlock(&qe->parent->lock); + if(use_weight) + AST_LIST_UNLOCK(&queues); + free(tmp); + goto out; + } + datastore->inheritance = DATASTORE_INHERIT_FOREVER; + dialed_interfaces = ast_calloc(1, sizeof(*dialed_interfaces)); + datastore->data = dialed_interfaces; + AST_LIST_HEAD_INIT(dialed_interfaces); + ast_channel_datastore_add(qe->chan, datastore); + } else + dialed_interfaces = datastore->data; + AST_LIST_LOCK(dialed_interfaces); + AST_LIST_TRAVERSE(dialed_interfaces, di, list) { + /* XXX case sensitive ?? */ + if(!strcasecmp(cur->interface, di->interface)) { + dialed = 1; + break; + } + } + if (!dialed && strncasecmp(cur->interface, "Local/", 6)) { + if(!(di = ast_calloc(1, sizeof(*di) + strlen(cur->interface)))) { + ao2_ref(cur, -1); + AST_LIST_UNLOCK(dialed_interfaces); + ast_mutex_unlock(&qe->parent->lock); + if(use_weight) + AST_LIST_UNLOCK(&queues); + free(tmp); + goto out; + } + strcpy(di->interface, cur->interface); + AST_LIST_INSERT_TAIL(dialed_interfaces, di, list); + } else { + AST_LIST_UNLOCK(dialed_interfaces); + ast_log(LOG_DEBUG, "Skipping dialing interface '%s' since it has already been dialed\n", di->interface); + free(tmp); + continue; + } + AST_LIST_UNLOCK(dialed_interfaces); tmp->stillgoing = -1; tmp->member = cur; tmp->oldstatus = cur->status; @@ -2593,6 +2641,8 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce if (use_weight) AST_LIST_UNLOCK(&queues); lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT), forwardsallowed); + ast_channel_datastore_remove(qe->chan, datastore); + ast_channel_datastore_free(datastore); ast_mutex_lock(&qe->parent->lock); if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY) { store_next(qe, outgoing); |