include "logger.h" and errno.h from asterisk.h - usage shows that they
[asterisk/asterisk.git] / apps / app_dial.c
index c792811..dfaa682 100644 (file)
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
 #include <sys/time.h>
 #include <sys/signal.h>
 #include <sys/stat.h>
@@ -42,7 +36,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 #include "asterisk/lock.h"
 #include "asterisk/file.h"
-#include "asterisk/logger.h"
 #include "asterisk/channel.h"
 #include "asterisk/pbx.h"
 #include "asterisk/options.h"
@@ -278,7 +271,7 @@ enum {
        OPT_ARG_ARRAY_SIZE,
 };
 
-AST_APP_OPTIONS(dial_exec_options, {
+AST_APP_OPTIONS(dial_exec_options, BEGIN_OPTIONS
        AST_APP_OPTION_ARG('A', OPT_ANNOUNCE, OPT_ARG_ANNOUNCE),
        AST_APP_OPTION('C', OPT_RESETCDR),
        AST_APP_OPTION('c', OPT_CANCEL_ELSEWHERE),
@@ -293,13 +286,15 @@ AST_APP_OPTIONS(dial_exec_options, {
        AST_APP_OPTION('i', OPT_IGNORE_FORWARDING),
        AST_APP_OPTION('k', OPT_CALLEE_PARK),
        AST_APP_OPTION('K', OPT_CALLER_PARK),
+       AST_APP_OPTION('k', OPT_CALLEE_PARK),
+       AST_APP_OPTION('K', OPT_CALLER_PARK),
        AST_APP_OPTION_ARG('L', OPT_DURATION_LIMIT, OPT_ARG_DURATION_LIMIT),
        AST_APP_OPTION_ARG('m', OPT_MUSICBACK, OPT_ARG_MUSICBACK),
        AST_APP_OPTION_ARG('M', OPT_CALLEE_MACRO, OPT_ARG_CALLEE_MACRO),
        AST_APP_OPTION('n', OPT_SCREEN_NOINTRO),
        AST_APP_OPTION('N', OPT_SCREEN_NOCLID),
-       AST_APP_OPTION_ARG('O', OPT_OPERMODE,OPT_ARG_OPERMODE),
        AST_APP_OPTION('o', OPT_ORIGINAL_CLID),
+       AST_APP_OPTION_ARG('O', OPT_OPERMODE,OPT_ARG_OPERMODE),
        AST_APP_OPTION('p', OPT_SCREENING),
        AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
        AST_APP_OPTION('r', OPT_RINGBACK),
@@ -309,7 +304,11 @@ AST_APP_OPTIONS(dial_exec_options, {
        AST_APP_OPTION_ARG('U', OPT_CALLEE_GOSUB, OPT_ARG_CALLEE_GOSUB),
        AST_APP_OPTION('w', OPT_CALLEE_MONITOR),
        AST_APP_OPTION('W', OPT_CALLER_MONITOR),
-});
+END_OPTIONS );
+
+#define CAN_EARLY_BRIDGE(flags) (!ast_test_flag64(flags, OPT_CALLEE_HANGUP | \
+       OPT_CALLER_HANGUP | OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER | \
+       OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR | OPT_CALLEE_PARK | OPT_CALLER_PARK))
 
 /*
  * The list of active channels
@@ -560,6 +559,9 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
        struct ast_channel *peer = NULL;
        /* single is set if only one destination is enabled */
        int single = outgoing && !outgoing->next && !ast_test_flag64(outgoing, OPT_MUSICBACK | OPT_RINGBACK);
+#ifdef HAVE_EPOLL
+       struct chanlist *epollo;
+#endif
        
        if (single) {
                /* Turn off hold music, etc */
@@ -567,7 +569,11 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
                /* If we are calling a single channel, make them compatible for in-band tone purpose */
                ast_channel_make_compatible(outgoing->chan, in);
        }
-       
+
+#ifdef HAVE_EPOLL
+       for (epollo = outgoing; epollo; epollo = epollo->next)
+               ast_poll_channel_add(in, epollo->chan);
+#endif 
        
        while (*to && !peer) {
                struct chanlist *o;
@@ -651,8 +657,9 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
                                                               DIAL_NOFORWARDHTML);
                                                ast_copy_string(c->dialcontext, "", sizeof(c->dialcontext));
                                                ast_copy_string(c->exten, "", sizeof(c->exten));
-                                               /* Setup early bridge if appropriate */
-                                               ast_channel_early_bridge(in, peer);
+                                               if (CAN_EARLY_BRIDGE(peerflags))
+                                                       /* Setup early bridge if appropriate */
+                                                       ast_channel_early_bridge(in, peer);
                                        }
                                        /* If call has been answered, then the eventual hangup is likely to be normal hangup */
                                        in->hangupcause = AST_CAUSE_NORMAL_CLEARING;
@@ -677,7 +684,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
                                case AST_CONTROL_RINGING:
                                        ast_verb(3, "%s is ringing\n", c->name);
                                        /* Setup early media if appropriate */
-                                       if (single)
+                                       if (single && CAN_EARLY_BRIDGE(peerflags))
                                                ast_channel_early_bridge(in, c);
                                        if (!(pa->sentringing) && !ast_test_flag64(outgoing, OPT_MUSICBACK)) {
                                                ast_indicate(in, AST_CONTROL_RINGING);
@@ -687,7 +694,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
                                case AST_CONTROL_PROGRESS:
                                        ast_verb(3, "%s is making progress passing it to %s\n", c->name, in->name);
                                        /* Setup early media if appropriate */
-                                       if (single)
+                                       if (single && CAN_EARLY_BRIDGE(peerflags))
                                                ast_channel_early_bridge(in, c);
                                        if (!ast_test_flag64(outgoing, OPT_RINGBACK))
                                                ast_indicate(in, AST_CONTROL_PROGRESS);
@@ -698,7 +705,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
                                        break;
                                case AST_CONTROL_PROCEEDING:
                                        ast_verb(3, "%s is proceeding passing it to %s\n", c->name, in->name);
-                                       if (single)
+                                       if (single && CAN_EARLY_BRIDGE(peerflags))
                                                ast_channel_early_bridge(in, c);
                                        if (!ast_test_flag64(outgoing, OPT_RINGBACK))
                                                ast_indicate(in, AST_CONTROL_PROCEEDING);
@@ -814,6 +821,11 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
                
        }
 
+#ifdef HAVE_EPOLL
+       for (epollo = outgoing; epollo; epollo = epollo->next)
+               ast_poll_channel_del(in, epollo->chan);
+#endif
+
        return peer;
 }
 
@@ -1387,6 +1399,7 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
                tc->cid.cid_pres = chan->cid.cid_pres;
                tc->cid.cid_ton = chan->cid.cid_ton;
                tc->cid.cid_tns = chan->cid.cid_tns;
+               tc->cid.cid_ani2 = chan->cid.cid_ani2;
                tc->adsicpe = chan->adsicpe;
                tc->transfercapability = chan->transfercapability;
 
@@ -1527,7 +1540,7 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
                        /* Ok, done. stop autoservice */
                        res = ast_autoservice_stop(chan);
                        if (digit > 0 && !res)
-                               res = ast_senddigit(chan, digit); 
+                               res = ast_senddigit(chan, digit, 0); 
                        else
                                res = digit;
 
@@ -1696,12 +1709,12 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
                        if (!ast_strlen_zero(dtmfcalled)) { 
                                if (option_verbose > 2)
                                        ast_verbose(VERBOSE_PREFIX_3 "Sending DTMF '%s' to the called party.\n", dtmfcalled);
-                               res = ast_dtmf_stream(peer,chan,dtmfcalled,250);
+                               res = ast_dtmf_stream(peer,chan,dtmfcalled,250,0);
                        }
                        if (!ast_strlen_zero(dtmfcalling)) {
                                if (option_verbose > 2)
                                        ast_verbose(VERBOSE_PREFIX_3 "Sending DTMF '%s' to the calling party.\n", dtmfcalling);
-                               res = ast_dtmf_stream(chan,peer,dtmfcalling,250);
+                               res = ast_dtmf_stream(chan,peer,dtmfcalling,250,0);
                        }
                }
                
@@ -1772,20 +1785,20 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
 
                if (ast_test_flag64(&opts, OPT_PEER_H) && ast_exists_extension(peer, peer->context, "h", 1, peer->cid.cid_num)) {
                        int autoloopflag;
+                       int found;
                        strcpy(peer->exten, "h");
                        peer->priority = 1;
                        autoloopflag = ast_test_flag(peer, AST_FLAG_IN_AUTOLOOP);       /* save value to restore at the end */
                        ast_set_flag(peer, AST_FLAG_IN_AUTOLOOP);
                        
-                       while (ast_exists_extension(peer, peer->context, peer->exten, peer->priority, peer->cid.cid_num)) {
-                               if ((res = ast_spawn_extension(peer, peer->context, peer->exten, peer->priority, peer->cid.cid_num))) {
-                                       /* Something bad happened, or a hangup has been requested. */
-                                       ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", peer->context, peer->exten, peer->priority, peer->name);
-                                       ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", peer->context, peer->exten, peer->priority, peer->name);
-                                       break;
-                               }
+                       while ((res = ast_spawn_extension(peer, peer->context, peer->exten, peer->priority, peer->cid.cid_num, &found,1))) {
                                peer->priority++;
                        }
+                       if (found && res) {
+                               /* Something bad happened, or a hangup has been requested. */
+                               ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", peer->context, peer->exten, peer->priority, peer->name);
+                               ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", peer->context, peer->exten, peer->priority, peer->name);
+                       }
                        ast_set2_flag(peer, autoloopflag, AST_FLAG_IN_AUTOLOOP);  /* set it back the way it was */
                }
                if (res != AST_PBX_NO_HANGUP_PEER) {
@@ -1956,7 +1969,7 @@ static int load_module(void)
        if (!con)
                ast_log(LOG_ERROR, "Dial virtual context 'app_dial_gosub_virtual_context' does not exist and unable to create\n");
        else
-               ast_add_extension2(con, 1, "s", 1, NULL, NULL, "KeepAlive", ast_strdup(""), ast_free, "app_dial");
+               ast_add_extension2(con, 1, "s", 1, NULL, NULL, "KeepAlive", ast_strdup(""), ast_free_ptr, "app_dial");
 
        res = ast_register_application(app, dial_exec, synopsis, descrip);
        res |= ast_register_application(rapp, retrydial_exec, rsynopsis, rdescrip);