aboutsummaryrefslogtreecommitdiffstats
path: root/main
diff options
context:
space:
mode:
authordvossel <dvossel@f38db490-d61c-443f-a65b-d21fe96a405b>2009-06-03 15:26:16 +0000
committerdvossel <dvossel@f38db490-d61c-443f-a65b-d21fe96a405b>2009-06-03 15:26:16 +0000
commit26530c23e074d50110d825efcc986b1c38d43f22 (patch)
tree80951f31760dca6d1367acf93f8323838ad6fab6 /main
parenta92d6019ce3c45f6033956e7f7b68838660cc28d (diff)
Merged revisions 198856 via svnmerge from
https://origsvn.digium.com/svn/asterisk/trunk ........ r198856 | dvossel | 2009-06-02 16:17:49 -0500 (Tue, 02 Jun 2009) | 10 lines Generic call forward api, ast_call_forward() The function ast_call_forward() forwards a call to an extension specified in an ast_channel's call_forward string. After an ast_channel is called, if the channel's call_forward string is set this function can be used to forward the call to a new channel and terminate the original one. I have included this api call in both channel.c's ast_request_and_dial() and feature.c's feature_request_and_dial(). App_dial and app_queue already contain call forward logic specific for their application and options. (closes issue #13630) Reported by: festr Review: https://reviewboard.asterisk.org/r/271/ ........ git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.6.1@198887 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'main')
-rw-r--r--main/channel.c98
-rw-r--r--main/features.c8
2 files changed, 100 insertions, 6 deletions
diff --git a/main/channel.c b/main/channel.c
index 15768b659..1e908533d 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -3535,6 +3535,91 @@ const char *ast_channel_reason2str(int reason)
}
}
+static void handle_cause(int cause, int *outstate)
+{
+ if (outstate) {
+ /* compute error and return */
+ if (cause == AST_CAUSE_BUSY)
+ *outstate = AST_CONTROL_BUSY;
+ else if (cause == AST_CAUSE_CONGESTION)
+ *outstate = AST_CONTROL_CONGESTION;
+ else
+ *outstate = 0;
+ }
+}
+
+struct ast_channel *ast_call_forward(struct ast_channel *caller, struct ast_channel *orig, int *timeout, int format, struct outgoing_helper *oh, int *outstate)
+{
+ char tmpchan[256];
+ struct ast_channel *new = NULL;
+ char *data, *type;
+ int cause = 0;
+
+ /* gather data and request the new forward channel */
+ ast_copy_string(tmpchan, orig->call_forward, sizeof(tmpchan));
+ if ((data = strchr(tmpchan, '/'))) {
+ *data++ = '\0';
+ type = tmpchan;
+ } else {
+ const char *forward_context;
+ ast_channel_lock(orig);
+ forward_context = pbx_builtin_getvar_helper(orig, "FORWARD_CONTEXT");
+ snprintf(tmpchan, sizeof(tmpchan), "%s@%s", orig->call_forward, S_OR(forward_context, orig->context));
+ ast_channel_unlock(orig);
+ data = tmpchan;
+ type = "Local";
+ }
+ if (!(new = ast_request(type, format, data, &cause))) {
+ ast_log(LOG_NOTICE, "Unable to create channel for call forward to '%s/%s' (cause = %d)\n", type, data, cause);
+ handle_cause(cause, outstate);
+ ast_hangup(orig);
+ return NULL;
+ }
+
+ /* Copy/inherit important information into new channel */
+ if (oh) {
+ if (oh->vars) {
+ ast_set_variables(new, oh->vars);
+ }
+ if (!ast_strlen_zero(oh->cid_num) && !ast_strlen_zero(oh->cid_name)) {
+ ast_set_callerid(new, oh->cid_num, oh->cid_name, oh->cid_num);
+ }
+ if (oh->parent_channel) {
+ ast_channel_inherit_variables(oh->parent_channel, new);
+ ast_channel_datastore_inherit(oh->parent_channel, new);
+ }
+ if (oh->account) {
+ ast_cdr_setaccount(new, oh->account);
+ }
+ } else if (caller) { /* no outgoing helper so use caller if avaliable */
+ ast_channel_inherit_variables(caller, new);
+ ast_channel_datastore_inherit(caller, new);
+ }
+
+ ast_channel_lock(orig);
+ while (ast_channel_trylock(new)) {
+ CHANNEL_DEADLOCK_AVOIDANCE(orig);
+ }
+ ast_copy_flags(new->cdr, orig->cdr, AST_CDR_FLAG_ORIGINATED);
+ ast_string_field_set(new, accountcode, orig->accountcode);
+ if (!ast_strlen_zero(orig->cid.cid_num) && !ast_strlen_zero(new->cid.cid_name)) {
+ ast_set_callerid(new, orig->cid.cid_num, orig->cid.cid_name, orig->cid.cid_num);
+ }
+ ast_channel_unlock(new);
+ ast_channel_unlock(orig);
+
+ /* call new channel */
+ if ((*timeout = ast_call(new, data, 0))) {
+ ast_log(LOG_NOTICE, "Unable to call forward to channel %s/%s\n", type, (char *)data);
+ ast_hangup(orig);
+ ast_hangup(new);
+ return NULL;
+ }
+ ast_hangup(orig);
+
+ return new;
+}
+
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 dummy_outstate;
@@ -3551,11 +3636,7 @@ struct ast_channel *__ast_request_and_dial(const char *type, int format, void *d
chan = ast_request(type, format, data, &cause);
if (!chan) {
ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
- /* compute error and return */
- if (cause == AST_CAUSE_BUSY)
- *outstate = AST_CONTROL_BUSY;
- else if (cause == AST_CAUSE_CONGESTION)
- *outstate = AST_CONTROL_CONGESTION;
+ handle_cause(cause, outstate);
return NULL;
}
@@ -3586,6 +3667,13 @@ struct ast_channel *__ast_request_and_dial(const char *type, int format, void *d
break;
if (timeout > -1)
timeout = res;
+ if (!ast_strlen_zero(chan->call_forward)) {
+ if (!(chan = ast_call_forward(NULL, chan, &timeout, format, oh, outstate))) {
+ return NULL;
+ }
+ continue;
+ }
+
f = ast_read(chan);
if (!f) {
*outstate = AST_CONTROL_HANGUP;
diff --git a/main/features.c b/main/features.c
index 86347bb46..57fc12c0c 100644
--- a/main/features.c
+++ b/main/features.c
@@ -2155,7 +2155,13 @@ static struct ast_channel *ast_feature_request_and_dial(struct ast_channel *call
if (!active_channel)
continue;
- if (chan && (chan == active_channel)){
+ if (chan && (chan == active_channel)) {
+ if (!ast_strlen_zero(chan->call_forward)) {
+ if (!(chan = ast_call_forward(caller, chan, &to, format, NULL, outstate))) {
+ return NULL;
+ }
+ continue;
+ }
f = ast_read(chan);
if (f == NULL) { /*doh! where'd he go?*/
state = AST_CONTROL_HANGUP;