Wed Aug 7 17:15:47 2019

Asterisk developer's documentation


app_dial.c File Reference

dial() & retrydial() - Trivial application to dial a channel and send an URL on answer More...

#include "asterisk.h"
#include <sys/time.h>
#include <sys/signal.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include "asterisk/paths.h"
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/say.h"
#include "asterisk/config.h"
#include "asterisk/features.h"
#include "asterisk/musiconhold.h"
#include "asterisk/callerid.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"
#include "asterisk/causes.h"
#include "asterisk/rtp_engine.h"
#include "asterisk/cdr.h"
#include "asterisk/manager.h"
#include "asterisk/privacy.h"
#include "asterisk/stringfields.h"
#include "asterisk/global_datastores.h"
#include "asterisk/dsp.h"
#include "asterisk/cel.h"
#include "asterisk/aoc.h"
#include "asterisk/ccss.h"
#include "asterisk/indications.h"
#include "asterisk/framehook.h"

Go to the source code of this file.

Data Structures

struct  cause_args
struct  chanlist
 List of channel drivers. More...
struct  privacy_args

Defines

#define AST_MAX_WATCHERS   256
#define CAN_EARLY_BRIDGE(flags, chan, peer)
#define DIAL_CALLERID_ABSENT   (1LLU << 33)
#define DIAL_NOFORWARDHTML   (1LLU << 32)
#define DIAL_STILLGOING   (1LLU << 31)
#define OPT_CALLEE_GO_ON   (1LLU << 36)
#define OPT_CALLER_ANSWER   (1LLU << 40)
#define OPT_CANCEL_ELSEWHERE   (1LLU << 34)
#define OPT_CANCEL_TIMEOUT   (1LLU << 37)
#define OPT_FORCE_CID_PRES   (1LLU << 39)
#define OPT_FORCE_CID_TAG   (1LLU << 38)
#define OPT_PEER_H   (1LLU << 35)

Enumerations

enum  {
  OPT_ANNOUNCE = (1 << 0), OPT_RESETCDR = (1 << 1), OPT_DTMF_EXIT = (1 << 2), OPT_SENDDTMF = (1 << 3),
  OPT_FORCECLID = (1 << 4), OPT_GO_ON = (1 << 5), OPT_CALLEE_HANGUP = (1 << 6), OPT_CALLER_HANGUP = (1 << 7),
  OPT_ORIGINAL_CLID = (1 << 8), OPT_DURATION_LIMIT = (1 << 9), OPT_MUSICBACK = (1 << 10), OPT_CALLEE_MACRO = (1 << 11),
  OPT_SCREEN_NOINTRO = (1 << 12), OPT_SCREEN_NOCALLERID = (1 << 13), OPT_IGNORE_CONNECTEDLINE = (1 << 14), OPT_SCREENING = (1 << 15),
  OPT_PRIVACY = (1 << 16), OPT_RINGBACK = (1 << 17), OPT_DURATION_STOP = (1 << 18), OPT_CALLEE_TRANSFER = (1 << 19),
  OPT_CALLER_TRANSFER = (1 << 20), OPT_CALLEE_MONITOR = (1 << 21), OPT_CALLER_MONITOR = (1 << 22), OPT_GOTO = (1 << 23),
  OPT_OPERMODE = (1 << 24), OPT_CALLEE_PARK = (1 << 25), OPT_CALLER_PARK = (1 << 26), OPT_IGNORE_FORWARDING = (1 << 27),
  OPT_CALLEE_GOSUB = (1 << 28), OPT_CALLEE_MIXMONITOR = (1 << 29), OPT_CALLER_MIXMONITOR = (1 << 30)
}
enum  {
  OPT_ARG_ANNOUNCE = 0, OPT_ARG_SENDDTMF, OPT_ARG_GOTO, OPT_ARG_DURATION_LIMIT,
  OPT_ARG_MUSICBACK, OPT_ARG_CALLEE_MACRO, OPT_ARG_RINGBACK, OPT_ARG_CALLEE_GOSUB,
  OPT_ARG_CALLEE_GO_ON, OPT_ARG_PRIVACY, OPT_ARG_DURATION_STOP, OPT_ARG_OPERMODE,
  OPT_ARG_SCREEN_NOINTRO, OPT_ARG_ORIGINAL_CLID, OPT_ARG_FORCECLID, OPT_ARG_FORCE_CID_TAG,
  OPT_ARG_FORCE_CID_PRES, OPT_ARG_ARRAY_SIZE
}

Functions

 AST_APP_OPTIONS (dial_exec_options, BEGIN_OPTIONS AST_APP_OPTION_ARG('A', OPT_ANNOUNCE, OPT_ARG_ANNOUNCE), AST_APP_OPTION('a', OPT_CALLER_ANSWER), AST_APP_OPTION('C', OPT_RESETCDR), AST_APP_OPTION('c', OPT_CANCEL_ELSEWHERE), AST_APP_OPTION('d', OPT_DTMF_EXIT), AST_APP_OPTION_ARG('D', OPT_SENDDTMF, OPT_ARG_SENDDTMF), AST_APP_OPTION('e', OPT_PEER_H), AST_APP_OPTION_ARG('f', OPT_FORCECLID, OPT_ARG_FORCECLID), AST_APP_OPTION_ARG('F', OPT_CALLEE_GO_ON, OPT_ARG_CALLEE_GO_ON), AST_APP_OPTION('g', OPT_GO_ON), AST_APP_OPTION_ARG('G', OPT_GOTO, OPT_ARG_GOTO), AST_APP_OPTION('h', OPT_CALLEE_HANGUP), AST_APP_OPTION('H', OPT_CALLER_HANGUP), AST_APP_OPTION('i', OPT_IGNORE_FORWARDING), AST_APP_OPTION('I', OPT_IGNORE_CONNECTEDLINE), 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_ARG('n', OPT_SCREEN_NOINTRO, OPT_ARG_SCREEN_NOINTRO), AST_APP_OPTION('N', OPT_SCREEN_NOCALLERID), AST_APP_OPTION_ARG('o', OPT_ORIGINAL_CLID, OPT_ARG_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_ARG('r', OPT_RINGBACK, OPT_ARG_RINGBACK), AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP), AST_APP_OPTION_ARG('s', OPT_FORCE_CID_TAG, OPT_ARG_FORCE_CID_TAG), AST_APP_OPTION_ARG('u', OPT_FORCE_CID_PRES, OPT_ARG_FORCE_CID_PRES), AST_APP_OPTION('t', OPT_CALLEE_TRANSFER), AST_APP_OPTION('T', OPT_CALLER_TRANSFER), 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), AST_APP_OPTION('x', OPT_CALLEE_MIXMONITOR), AST_APP_OPTION('X', OPT_CALLER_MIXMONITOR), AST_APP_OPTION('z', OPT_CANCEL_TIMEOUT), END_OPTIONS)
 AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Dialing Application")
static void chanlist_free (struct chanlist *outgoing)
static int detect_disconnect (struct ast_channel *chan, char code, struct ast_str **featurecode)
static int dial_exec (struct ast_channel *chan, const char *data)
static int dial_exec_full (struct ast_channel *chan, const char *data, struct ast_flags64 *peerflags, int *continue_exec)
static int dial_handle_playtones (struct ast_channel *chan, const char *data)
static void do_forward (struct chanlist *o, struct cause_args *num, struct ast_flags64 *peerflags, int single, int caller_entertained, int *to, struct ast_party_id *forced_clid, struct ast_party_id *stored_clid)
static void end_bridge_callback (void *data)
static void end_bridge_callback_data_fixup (struct ast_bridge_config *bconfig, struct ast_channel *originator, struct ast_channel *terminator)
static const char * get_cid_name (char *name, int namelen, struct ast_channel *chan)
static void handle_cause (int cause, struct cause_args *num)
static void hanguptree (struct chanlist *outgoing, struct ast_channel *exception, int answered_elsewhere)
static int load_module (void)
static int onedigit_goto (struct ast_channel *chan, const char *context, char exten, int pri)
static void replace_macro_delimiter (char *s)
static int retrydial_exec (struct ast_channel *chan, const char *data)
static void senddialendevent (struct ast_channel *src, const char *dialstatus)
static void senddialevent (struct ast_channel *src, struct ast_channel *dst, const char *dialstring)
static int setup_privacy_args (struct privacy_args *pa, struct ast_flags64 *opts, char *opt_args[], struct ast_channel *chan)
 returns 1 if successful, 0 or <0 if the caller should 'goto out'
static int unload_module (void)
static int valid_priv_reply (struct ast_flags64 *opts, int res)
static struct ast_channelwait_for_answer (struct ast_channel *in, struct chanlist *outgoing, int *to, struct ast_flags64 *peerflags, char *opt_args[], struct privacy_args *pa, const struct cause_args *num_in, int *result, char *dtmf_progress, const int ignore_cc, struct ast_party_id *forced_clid, struct ast_party_id *stored_clid)

Variables

static const char app [] = "Dial"
static const char rapp [] = "RetryDial"

Detailed Description

dial() & retrydial() - Trivial application to dial a channel and send an URL on answer

Author:
Mark Spencer <markster@digium.com>

Definition in file app_dial.c.


Define Documentation

#define AST_MAX_WATCHERS   256

Definition at line 705 of file app_dial.c.

Referenced by monitor_dial(), and wait_for_answer().

#define CAN_EARLY_BRIDGE ( flags,
chan,
peer   ) 

Definition at line 654 of file app_dial.c.

Referenced by dial_exec_full(), do_forward(), and wait_for_answer().

#define DIAL_CALLERID_ABSENT   (1LLU << 33)

Definition at line 582 of file app_dial.c.

Referenced by dial_exec_full(), do_forward(), and wait_for_answer().

#define DIAL_NOFORWARDHTML   (1LLU << 32)

Definition at line 581 of file app_dial.c.

Referenced by dial_exec_full(), and wait_for_answer().

#define DIAL_STILLGOING   (1LLU << 31)

Definition at line 580 of file app_dial.c.

Referenced by dial_exec_full(), do_forward(), and wait_for_answer().

#define OPT_CALLEE_GO_ON   (1LLU << 36)

Definition at line 585 of file app_dial.c.

Referenced by dial_exec_full().

#define OPT_CALLER_ANSWER   (1LLU << 40)

Definition at line 589 of file app_dial.c.

Referenced by dial_exec_full().

#define OPT_CANCEL_ELSEWHERE   (1LLU << 34)

Definition at line 583 of file app_dial.c.

Referenced by dial_exec_full().

#define OPT_CANCEL_TIMEOUT   (1LLU << 37)

Definition at line 586 of file app_dial.c.

Referenced by dial_exec_full(), and do_forward().

#define OPT_FORCE_CID_PRES   (1LLU << 39)

Definition at line 588 of file app_dial.c.

Referenced by dial_exec_full().

#define OPT_FORCE_CID_TAG   (1LLU << 38)

Definition at line 587 of file app_dial.c.

Referenced by dial_exec_full().

#define OPT_PEER_H   (1LLU << 35)

Definition at line 584 of file app_dial.c.

Referenced by dial_exec_full().


Enumeration Type Documentation

anonymous enum
Enumerator:
OPT_ANNOUNCE 
OPT_RESETCDR 
OPT_DTMF_EXIT 
OPT_SENDDTMF 
OPT_FORCECLID 
OPT_GO_ON 
OPT_CALLEE_HANGUP 
OPT_CALLER_HANGUP 
OPT_ORIGINAL_CLID 
OPT_DURATION_LIMIT 
OPT_MUSICBACK 
OPT_CALLEE_MACRO 
OPT_SCREEN_NOINTRO 
OPT_SCREEN_NOCALLERID 
OPT_IGNORE_CONNECTEDLINE 
OPT_SCREENING 
OPT_PRIVACY 
OPT_RINGBACK 
OPT_DURATION_STOP 
OPT_CALLEE_TRANSFER 
OPT_CALLER_TRANSFER 
OPT_CALLEE_MONITOR 
OPT_CALLER_MONITOR 
OPT_GOTO 
OPT_OPERMODE 
OPT_CALLEE_PARK 
OPT_CALLER_PARK 
OPT_IGNORE_FORWARDING 
OPT_CALLEE_GOSUB 
OPT_CALLEE_MIXMONITOR 
OPT_CALLER_MIXMONITOR 

Definition at line 545 of file app_dial.c.

00545      {
00546    OPT_ANNOUNCE =          (1 << 0),
00547    OPT_RESETCDR =          (1 << 1),
00548    OPT_DTMF_EXIT =         (1 << 2),
00549    OPT_SENDDTMF =          (1 << 3),
00550    OPT_FORCECLID =         (1 << 4),
00551    OPT_GO_ON =             (1 << 5),
00552    OPT_CALLEE_HANGUP =     (1 << 6),
00553    OPT_CALLER_HANGUP =     (1 << 7),
00554    OPT_ORIGINAL_CLID =     (1 << 8),
00555    OPT_DURATION_LIMIT =    (1 << 9),
00556    OPT_MUSICBACK =         (1 << 10),
00557    OPT_CALLEE_MACRO =      (1 << 11),
00558    OPT_SCREEN_NOINTRO =    (1 << 12),
00559    OPT_SCREEN_NOCALLERID = (1 << 13),
00560    OPT_IGNORE_CONNECTEDLINE = (1 << 14),
00561    OPT_SCREENING =         (1 << 15),
00562    OPT_PRIVACY =           (1 << 16),
00563    OPT_RINGBACK =          (1 << 17),
00564    OPT_DURATION_STOP =     (1 << 18),
00565    OPT_CALLEE_TRANSFER =   (1 << 19),
00566    OPT_CALLER_TRANSFER =   (1 << 20),
00567    OPT_CALLEE_MONITOR =    (1 << 21),
00568    OPT_CALLER_MONITOR =    (1 << 22),
00569    OPT_GOTO =              (1 << 23),
00570    OPT_OPERMODE =          (1 << 24),
00571    OPT_CALLEE_PARK =       (1 << 25),
00572    OPT_CALLER_PARK =       (1 << 26),
00573    OPT_IGNORE_FORWARDING = (1 << 27),
00574    OPT_CALLEE_GOSUB =      (1 << 28),
00575    OPT_CALLEE_MIXMONITOR = (1 << 29),
00576    OPT_CALLER_MIXMONITOR = (1 << 30),
00577 };

anonymous enum
Enumerator:
OPT_ARG_ANNOUNCE 
OPT_ARG_SENDDTMF 
OPT_ARG_GOTO 
OPT_ARG_DURATION_LIMIT 
OPT_ARG_MUSICBACK 
OPT_ARG_CALLEE_MACRO 
OPT_ARG_RINGBACK 
OPT_ARG_CALLEE_GOSUB 
OPT_ARG_CALLEE_GO_ON 
OPT_ARG_PRIVACY 
OPT_ARG_DURATION_STOP 
OPT_ARG_OPERMODE 
OPT_ARG_SCREEN_NOINTRO 
OPT_ARG_ORIGINAL_CLID 
OPT_ARG_FORCECLID 
OPT_ARG_FORCE_CID_TAG 
OPT_ARG_FORCE_CID_PRES 
OPT_ARG_ARRAY_SIZE 

Definition at line 591 of file app_dial.c.

00591      {
00592    OPT_ARG_ANNOUNCE = 0,
00593    OPT_ARG_SENDDTMF,
00594    OPT_ARG_GOTO,
00595    OPT_ARG_DURATION_LIMIT,
00596    OPT_ARG_MUSICBACK,
00597    OPT_ARG_CALLEE_MACRO,
00598    OPT_ARG_RINGBACK,
00599    OPT_ARG_CALLEE_GOSUB,
00600    OPT_ARG_CALLEE_GO_ON,
00601    OPT_ARG_PRIVACY,
00602    OPT_ARG_DURATION_STOP,
00603    OPT_ARG_OPERMODE,
00604    OPT_ARG_SCREEN_NOINTRO,
00605    OPT_ARG_ORIGINAL_CLID,
00606    OPT_ARG_FORCECLID,
00607    OPT_ARG_FORCE_CID_TAG,
00608    OPT_ARG_FORCE_CID_PRES,
00609    /* note: this entry _MUST_ be the last one in the enum */
00610    OPT_ARG_ARRAY_SIZE,
00611 };


Function Documentation

AST_APP_OPTIONS ( dial_exec_options  ,
BEGIN_OPTIONS   AST_APP_OPTION_ARG'A', OPT_ANNOUNCE, OPT_ARG_ANNOUNCE,
AST_APP_OPTION('a', OPT_CALLER_ANSWER)  ,
AST_APP_OPTION('C', OPT_RESETCDR)  ,
AST_APP_OPTION('c', OPT_CANCEL_ELSEWHERE)  ,
AST_APP_OPTION('d', OPT_DTMF_EXIT)  ,
AST_APP_OPTION_ARG('D', OPT_SENDDTMF, OPT_ARG_SENDDTMF)  ,
AST_APP_OPTION('e', OPT_PEER_H)  ,
AST_APP_OPTION_ARG('f', OPT_FORCECLID, OPT_ARG_FORCECLID)  ,
AST_APP_OPTION_ARG('F', OPT_CALLEE_GO_ON, OPT_ARG_CALLEE_GO_ON)  ,
AST_APP_OPTION('g', OPT_GO_ON)  ,
AST_APP_OPTION_ARG('G', OPT_GOTO, OPT_ARG_GOTO)  ,
AST_APP_OPTION('h', OPT_CALLEE_HANGUP)  ,
AST_APP_OPTION('H', OPT_CALLER_HANGUP)  ,
AST_APP_OPTION('i', OPT_IGNORE_FORWARDING)  ,
AST_APP_OPTION('I', OPT_IGNORE_CONNECTEDLINE)  ,
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_ARG('n', OPT_SCREEN_NOINTRO, OPT_ARG_SCREEN_NOINTRO)  ,
AST_APP_OPTION('N', OPT_SCREEN_NOCALLERID)  ,
AST_APP_OPTION_ARG('o', OPT_ORIGINAL_CLID, OPT_ARG_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_ARG('r', OPT_RINGBACK, OPT_ARG_RINGBACK)  ,
AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP)  ,
AST_APP_OPTION_ARG('s', OPT_FORCE_CID_TAG, OPT_ARG_FORCE_CID_TAG)  ,
AST_APP_OPTION_ARG('u', OPT_FORCE_CID_PRES, OPT_ARG_FORCE_CID_PRES)  ,
AST_APP_OPTION('t', OPT_CALLEE_TRANSFER)  ,
AST_APP_OPTION('T', OPT_CALLER_TRANSFER)  ,
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)  ,
AST_APP_OPTION('x', OPT_CALLEE_MIXMONITOR)  ,
AST_APP_OPTION('X', OPT_CALLER_MIXMONITOR)  ,
AST_APP_OPTION('z', OPT_CANCEL_TIMEOUT)  ,
END_OPTIONS   
)
AST_MODULE_INFO_STANDARD ( ASTERISK_GPL_KEY  ,
"Dialing Application"   
)
static void chanlist_free ( struct chanlist outgoing  )  [static]
static int detect_disconnect ( struct ast_channel chan,
char  code,
struct ast_str **  featurecode 
) [static]

Definition at line 1652 of file app_dial.c.

References ast_feature_detect(), AST_FEATURE_DISCONNECT, AST_FEATURE_RETURN_STOREDIGITS, ast_str_append(), ast_str_buffer(), ast_str_reset(), and ast_call_feature::feature_mask.

Referenced by wait_for_answer().

01653 {
01654    struct ast_flags features = { AST_FEATURE_DISCONNECT }; /* only concerned with disconnect feature */
01655    struct ast_call_feature feature = { 0, };
01656    int res;
01657 
01658    ast_str_append(featurecode, 1, "%c", code);
01659 
01660    res = ast_feature_detect(chan, &features, ast_str_buffer(*featurecode), &feature);
01661 
01662    if (res != AST_FEATURE_RETURN_STOREDIGITS) {
01663       ast_str_reset(*featurecode);
01664    }
01665    if (feature.feature_mask & AST_FEATURE_DISCONNECT) {
01666       return 1;
01667    }
01668 
01669    return 0;
01670 }

static int dial_exec ( struct ast_channel chan,
const char *  data 
) [static]

Definition at line 3055 of file app_dial.c.

References dial_exec_full().

Referenced by load_module().

03056 {
03057    struct ast_flags64 peerflags;
03058 
03059    memset(&peerflags, 0, sizeof(peerflags));
03060 
03061    return dial_exec_full(chan, data, &peerflags, NULL);
03062 }

static int dial_exec_full ( struct ast_channel chan,
const char *  data,
struct ast_flags64 peerflags,
int *  continue_exec 
) [static]

< TRUE if force CallerID on call forward only. Legacy behaviour.

Forced CallerID party information to send.

Note:
This will not have any malloced strings so do not free it.

Stored CallerID information if needed.

Note:
If OPT_ORIGINAL_CLID set then this is the o option CallerID. Otherwise it is the dialplan extension and hint name.
This will not have any malloced strings so do not free it.

CallerID party information to store.

Note:
This will not have any malloced strings so do not free it.

Definition at line 1987 of file app_dial.c.

References ast_channel::_state, accountcode, ast_channel::adsicpe, ast_cdr::answer, ast_channel::appl, args, ast_answer(), AST_APP_ARG, ast_app_group_set_channel(), ast_app_parse_options64(), ast_asprintf, ast_autoservice_start(), ast_autoservice_stop(), ast_bridge_call(), ast_bridge_timelimit(), ast_call(), ast_callerid_parse(), ast_calloc, ast_cause2str(), AST_CAUSE_ANSWERED_ELSEWHERE, AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, ast_cc_busy_interface(), ast_cc_call_failed(), ast_cc_call_init(), ast_cc_callback(), ast_cc_extension_monitor_add_dialstring(), AST_CDR_FLAG_DIALED, ast_cdr_reset(), ast_cdr_setanswer(), ast_cdr_setdestchan(), ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_datastore_inherit(), ast_channel_datastore_remove(), ast_channel_early_bridge(), ast_channel_get_device_name(), ast_channel_inherit_variables(), ast_channel_lock, ast_channel_make_compatible(), AST_CHANNEL_NAME, ast_channel_sendurl(), ast_channel_set_caller_event(), ast_channel_set_connected_line(), ast_channel_setoption(), ast_channel_supports_html(), ast_channel_trylock, ast_channel_unlock, ast_check_hangup(), ast_clear_flag, ast_connected_line_copy_from_caller(), AST_CONTROL_HANGUP, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, ast_copy_flags64, ast_copy_string(), ast_datastore_alloc, ast_datastore_free(), ast_deactivate_generator(), ast_debug, AST_DECLARE_APP_ARGS, AST_DIGIT_ANY, ast_dtmf_stream(), ast_exists_extension(), AST_FEATURE_AUTOMIXMON, AST_FEATURE_AUTOMON, AST_FEATURE_DISCONNECT, AST_FEATURE_NO_H_EXTEN, AST_FEATURE_PARKCALL, AST_FEATURE_REDIRECT, ast_filedelete(), ast_fileexists(), AST_FLAG_ANSWERED_ELSEWHERE, AST_FLAG_END_DTMF_ONLY, AST_FLAG_IN_AUTOLOOP, AST_FRAME_CONTROL, AST_FRAME_DTMF_END, ast_free, ast_frfree, ast_goto_if_exists(), ast_hangup(), ast_ignore_cc(), ast_indicate(), AST_LIST_HEAD, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), AST_MAX_EXTENSION, ast_moh_start(), ast_moh_stop(), AST_OPTION_OPRMODE, ast_parse_caller_presentation(), ast_parseable_goto(), ast_party_caller_set_init(), ast_party_connected_line_copy(), ast_party_connected_line_set_init(), ast_party_id_init(), ast_party_id_set_init(), ast_party_redirecting_copy(), AST_PBX_INCOMPLETE, ast_pbx_run_args(), ast_pbx_start(), AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, AST_PRIVACY_UNKNOWN, ast_read(), ast_request(), ast_rtp_instance_early_bridge_make_compatible(), ast_sched_runq(), ast_sched_wait(), ast_senddigit(), ast_set2_flag, ast_set2_flag64, ast_set_flag, ast_set_flag64, ast_spawn_extension(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_streamfile(), ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_test_flag64, ast_tvadd(), ast_tvnow(), ast_tvzero(), ast_verb, ast_waitfor_n(), ast_channel::caller, CAN_EARLY_BRIDGE, ast_channel::cdr, chanlist::chan, chanlist_free(), CHANNEL_DEADLOCK_AVOIDANCE, ast_channel::connected, chanlist::connected, ast_channel::context, ast_channel::data, ast_datastore::data, DATASTORE_INHERIT_FOREVER, di, DIAL_CALLERID_ABSENT, dial_handle_playtones(), DIAL_NOFORWARDHTML, DIAL_STILLGOING, dialcontext, ast_channel::dialed, dialed_interface_info, end_bridge_callback(), ast_bridge_config::end_bridge_callback, ast_bridge_config::end_bridge_callback_data, end_bridge_callback_data_fixup(), ast_bridge_config::end_bridge_callback_data_fixup, ast_bridge_config::end_sound, ast_channel::exten, ast_bridge_config::features_callee, ast_bridge_config::features_caller, ast_flags64::flags, ast_frame::frametype, get_cid_name(), handle_cause(), ast_channel::hangupcause, hanguptree(), ast_party_connected_line::id, ast_party_caller::id, ast_datastore::inheritance, ast_frame_subclass::integer, ast_dialed_interface::interface, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_channel::macrocontext, ast_channel::macroexten, oprmode::mode, moh, musicclass, ast_party_id::name, ast_channel::nativeformats, chanlist::next, ast_pbx_args::no_hangup_chan, ast_party_id::number, OPT_ANNOUNCE, OPT_ARG_ANNOUNCE, OPT_ARG_ARRAY_SIZE, OPT_ARG_CALLEE_GO_ON, OPT_ARG_CALLEE_GOSUB, OPT_ARG_CALLEE_MACRO, OPT_ARG_DURATION_LIMIT, OPT_ARG_DURATION_STOP, OPT_ARG_FORCE_CID_PRES, OPT_ARG_FORCE_CID_TAG, OPT_ARG_FORCECLID, OPT_ARG_GOTO, OPT_ARG_OPERMODE, OPT_ARG_ORIGINAL_CLID, OPT_ARG_PRIVACY, OPT_ARG_RINGBACK, OPT_ARG_SCREEN_NOINTRO, OPT_ARG_SENDDTMF, OPT_CALLEE_GO_ON, OPT_CALLEE_GOSUB, OPT_CALLEE_HANGUP, OPT_CALLEE_MACRO, OPT_CALLEE_MIXMONITOR, OPT_CALLEE_MONITOR, OPT_CALLEE_PARK, OPT_CALLEE_TRANSFER, OPT_CALLER_ANSWER, OPT_CALLER_HANGUP, OPT_CALLER_MIXMONITOR, OPT_CALLER_MONITOR, OPT_CALLER_PARK, OPT_CALLER_TRANSFER, OPT_CANCEL_ELSEWHERE, OPT_CANCEL_TIMEOUT, OPT_DTMF_EXIT, OPT_DURATION_LIMIT, OPT_DURATION_STOP, OPT_FORCE_CID_PRES, OPT_FORCE_CID_TAG, OPT_FORCECLID, OPT_GO_ON, OPT_GOTO, OPT_IGNORE_CONNECTEDLINE, OPT_IGNORE_FORWARDING, OPT_MUSICBACK, OPT_OPERMODE, OPT_ORIGINAL_CLID, OPT_PEER_H, OPT_PRIVACY, OPT_RESETCDR, OPT_RINGBACK, OPT_SCREEN_NOINTRO, OPT_SCREENING, OPT_SENDDTMF, parse(), pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_exec(), pbx_findapp(), oprmode::peer, ast_party_number::presentation, ast_channel::priority, privacy_args::privdb_val, privacy_args::privintro, ast_channel::redirecting, replace_macro_delimiter(), S_COR, S_OR, ast_channel::sched, senddialendevent(), senddialevent(), privacy_args::sentringing, setup_privacy_args(), ast_bridge_config::start_sound, privacy_args::status, ast_party_subaddress::str, ast_party_name::str, ast_party_number::str, ast_channel::stream, ast_party_id::subaddress, ast_frame::subclass, ast_party_id::tag, ast_channel::tech, ast_channel::timingfunc, ast_channel::transfercapability, ast_party_dialed::transit_network_select, url, ast_party_number::valid, ast_party_name::valid, ast_channel::visible_indication, wait_for_answer(), ast_bridge_config::warning_sound, and ast_channel::whentohangup.

Referenced by dial_exec(), and retrydial_exec().

01988 {
01989    int res = -1; /* default: error */
01990    char *rest, *cur; /* scan the list of destinations */
01991    struct chanlist *outgoing = NULL; /* list of destinations */
01992    struct ast_channel *peer;
01993    int to; /* timeout */
01994    struct cause_args num = { chan, 0, 0, 0 };
01995    int cause;
01996    char numsubst[256];
01997 
01998    struct ast_bridge_config config = { { 0, } };
01999    struct timeval calldurationlimit = { 0, };
02000    char *dtmfcalled = NULL, *dtmfcalling = NULL, *dtmf_progress=NULL;
02001    struct privacy_args pa = {
02002       .sentringing = 0,
02003       .privdb_val = 0,
02004       .status = "INVALIDARGS",
02005    };
02006    int sentringing = 0, moh = 0;
02007    const char *outbound_group = NULL;
02008    int result = 0;
02009    char *parse;
02010    int opermode = 0;
02011    int delprivintro = 0;
02012    AST_DECLARE_APP_ARGS(args,
02013       AST_APP_ARG(peers);
02014       AST_APP_ARG(timeout);
02015       AST_APP_ARG(options);
02016       AST_APP_ARG(url);
02017    );
02018    struct ast_flags64 opts = { 0, };
02019    char *opt_args[OPT_ARG_ARRAY_SIZE];
02020    struct ast_datastore *datastore = NULL;
02021    int fulldial = 0, num_dialed = 0;
02022    int ignore_cc = 0;
02023    char device_name[AST_CHANNEL_NAME];
02024    char forced_clid_name[AST_MAX_EXTENSION];
02025    char stored_clid_name[AST_MAX_EXTENSION];
02026    int force_forwards_only;   /*!< TRUE if force CallerID on call forward only. Legacy behaviour.*/
02027    /*!
02028     * \brief Forced CallerID party information to send.
02029     * \note This will not have any malloced strings so do not free it.
02030     */
02031    struct ast_party_id forced_clid;
02032    /*!
02033     * \brief Stored CallerID information if needed.
02034     *
02035     * \note If OPT_ORIGINAL_CLID set then this is the o option
02036     * CallerID.  Otherwise it is the dialplan extension and hint
02037     * name.
02038     *
02039     * \note This will not have any malloced strings so do not free it.
02040     */
02041    struct ast_party_id stored_clid;
02042    /*!
02043     * \brief CallerID party information to store.
02044     * \note This will not have any malloced strings so do not free it.
02045     */
02046    struct ast_party_caller caller;
02047 
02048    /* Reset all DIAL variables back to blank, to prevent confusion (in case we don't reset all of them). */
02049    pbx_builtin_setvar_helper(chan, "DIALSTATUS", "");
02050    pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", "");
02051    pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", "");
02052    pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", "");
02053    pbx_builtin_setvar_helper(chan, "DIALEDTIME", "");
02054 
02055    if (ast_strlen_zero(data)) {
02056       ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n");
02057       pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
02058       return -1;
02059    }
02060 
02061    parse = ast_strdupa(data);
02062 
02063    AST_STANDARD_APP_ARGS(args, parse);
02064 
02065    if (!ast_strlen_zero(args.options) &&
02066       ast_app_parse_options64(dial_exec_options, &opts, opt_args, args.options)) {
02067       pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
02068       goto done;
02069    }
02070 
02071    if (ast_strlen_zero(args.peers)) {
02072       ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n");
02073       pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
02074       goto done;
02075    }
02076 
02077    if (ast_cc_call_init(chan, &ignore_cc)) {
02078       goto done;
02079    }
02080 
02081    if (ast_test_flag64(&opts, OPT_SCREEN_NOINTRO) && !ast_strlen_zero(opt_args[OPT_ARG_SCREEN_NOINTRO])) {
02082       delprivintro = atoi(opt_args[OPT_ARG_SCREEN_NOINTRO]);
02083 
02084       if (delprivintro < 0 || delprivintro > 1) {
02085          ast_log(LOG_WARNING, "Unknown argument %d specified to n option, ignoring\n", delprivintro);
02086          delprivintro = 0;
02087       }
02088    }
02089 
02090    if (!ast_test_flag64(&opts, OPT_RINGBACK)) {
02091       opt_args[OPT_ARG_RINGBACK] = NULL;
02092    }
02093 
02094    if (ast_test_flag64(&opts, OPT_OPERMODE)) {
02095       opermode = ast_strlen_zero(opt_args[OPT_ARG_OPERMODE]) ? 1 : atoi(opt_args[OPT_ARG_OPERMODE]);
02096       ast_verb(3, "Setting operator services mode to %d.\n", opermode);
02097    }
02098 
02099    if (ast_test_flag64(&opts, OPT_DURATION_STOP) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_STOP])) {
02100       calldurationlimit.tv_sec = atoi(opt_args[OPT_ARG_DURATION_STOP]);
02101       if (!calldurationlimit.tv_sec) {
02102          ast_log(LOG_WARNING, "Dial does not accept S(%s), hanging up.\n", opt_args[OPT_ARG_DURATION_STOP]);
02103          pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
02104          goto done;
02105       }
02106       ast_verb(3, "Setting call duration limit to %.3lf seconds.\n", calldurationlimit.tv_sec + calldurationlimit.tv_usec / 1000000.0);
02107    }
02108 
02109    if (ast_test_flag64(&opts, OPT_SENDDTMF) && !ast_strlen_zero(opt_args[OPT_ARG_SENDDTMF])) {
02110       dtmf_progress = opt_args[OPT_ARG_SENDDTMF];
02111       dtmfcalled = strsep(&dtmf_progress, ":");
02112       dtmfcalling = strsep(&dtmf_progress, ":");
02113    }
02114 
02115    if (ast_test_flag64(&opts, OPT_DURATION_LIMIT) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_LIMIT])) {
02116       if (ast_bridge_timelimit(chan, &config, opt_args[OPT_ARG_DURATION_LIMIT], &calldurationlimit))
02117          goto done;
02118    }
02119 
02120    /* Setup the forced CallerID information to send if used. */
02121    ast_party_id_init(&forced_clid);
02122    force_forwards_only = 0;
02123    if (ast_test_flag64(&opts, OPT_FORCECLID)) {
02124       if (ast_strlen_zero(opt_args[OPT_ARG_FORCECLID])) {
02125          ast_channel_lock(chan);
02126          forced_clid.number.str = ast_strdupa(S_OR(chan->macroexten, chan->exten));
02127          ast_channel_unlock(chan);
02128          forced_clid_name[0] = '\0';
02129          forced_clid.name.str = (char *) get_cid_name(forced_clid_name,
02130             sizeof(forced_clid_name), chan);
02131          force_forwards_only = 1;
02132       } else {
02133          /* Note: The opt_args[OPT_ARG_FORCECLID] string value is altered here. */
02134          ast_callerid_parse(opt_args[OPT_ARG_FORCECLID], &forced_clid.name.str,
02135             &forced_clid.number.str);
02136       }
02137       if (!ast_strlen_zero(forced_clid.name.str)) {
02138          forced_clid.name.valid = 1;
02139       }
02140       if (!ast_strlen_zero(forced_clid.number.str)) {
02141          forced_clid.number.valid = 1;
02142       }
02143    }
02144    if (ast_test_flag64(&opts, OPT_FORCE_CID_TAG)
02145       && !ast_strlen_zero(opt_args[OPT_ARG_FORCE_CID_TAG])) {
02146       forced_clid.tag = opt_args[OPT_ARG_FORCE_CID_TAG];
02147    }
02148    forced_clid.number.presentation = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
02149    if (ast_test_flag64(&opts, OPT_FORCE_CID_PRES)
02150       && !ast_strlen_zero(opt_args[OPT_ARG_FORCE_CID_PRES])) {
02151       int pres;
02152 
02153       pres = ast_parse_caller_presentation(opt_args[OPT_ARG_FORCE_CID_PRES]);
02154       if (0 <= pres) {
02155          forced_clid.number.presentation = pres;
02156       }
02157    }
02158 
02159    /* Setup the stored CallerID information if needed. */
02160    ast_party_id_init(&stored_clid);
02161    if (ast_test_flag64(&opts, OPT_ORIGINAL_CLID)) {
02162       if (ast_strlen_zero(opt_args[OPT_ARG_ORIGINAL_CLID])) {
02163          ast_channel_lock(chan);
02164          ast_party_id_set_init(&stored_clid, &chan->caller.id);
02165          if (!ast_strlen_zero(chan->caller.id.name.str)) {
02166             stored_clid.name.str = ast_strdupa(chan->caller.id.name.str);
02167          }
02168          if (!ast_strlen_zero(chan->caller.id.number.str)) {
02169             stored_clid.number.str = ast_strdupa(chan->caller.id.number.str);
02170          }
02171          if (!ast_strlen_zero(chan->caller.id.subaddress.str)) {
02172             stored_clid.subaddress.str = ast_strdupa(chan->caller.id.subaddress.str);
02173          }
02174          if (!ast_strlen_zero(chan->caller.id.tag)) {
02175             stored_clid.tag = ast_strdupa(chan->caller.id.tag);
02176          }
02177          ast_channel_unlock(chan);
02178       } else {
02179          /* Note: The opt_args[OPT_ARG_ORIGINAL_CLID] string value is altered here. */
02180          ast_callerid_parse(opt_args[OPT_ARG_ORIGINAL_CLID], &stored_clid.name.str,
02181             &stored_clid.number.str);
02182          if (!ast_strlen_zero(stored_clid.name.str)) {
02183             stored_clid.name.valid = 1;
02184          }
02185          if (!ast_strlen_zero(stored_clid.number.str)) {
02186             stored_clid.number.valid = 1;
02187          }
02188       }
02189    } else {
02190       /*
02191        * In case the new channel has no preset CallerID number by the
02192        * channel driver, setup the dialplan extension and hint name.
02193        */
02194       stored_clid_name[0] = '\0';
02195       stored_clid.name.str = (char *) get_cid_name(stored_clid_name,
02196          sizeof(stored_clid_name), chan);
02197       if (ast_strlen_zero(stored_clid.name.str)) {
02198          stored_clid.name.str = NULL;
02199       } else {
02200          stored_clid.name.valid = 1;
02201       }
02202       ast_channel_lock(chan);
02203       stored_clid.number.str = ast_strdupa(S_OR(chan->macroexten, chan->exten));
02204       stored_clid.number.valid = 1;
02205       ast_channel_unlock(chan);
02206    }
02207 
02208    if (ast_test_flag64(&opts, OPT_RESETCDR) && chan->cdr)
02209       ast_cdr_reset(chan->cdr, NULL);
02210    if (ast_test_flag64(&opts, OPT_PRIVACY) && ast_strlen_zero(opt_args[OPT_ARG_PRIVACY]))
02211       opt_args[OPT_ARG_PRIVACY] = ast_strdupa(chan->exten);
02212 
02213    if (ast_test_flag64(&opts, OPT_PRIVACY) || ast_test_flag64(&opts, OPT_SCREENING)) {
02214       res = setup_privacy_args(&pa, &opts, opt_args, chan);
02215       if (res <= 0)
02216          goto out;
02217       res = -1; /* reset default */
02218    }
02219 
02220    if (continue_exec)
02221       *continue_exec = 0;
02222 
02223    /* If a channel group has been specified, get it for use when we create peer channels */
02224 
02225    ast_channel_lock(chan);
02226    if ((outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP_ONCE"))) {
02227       outbound_group = ast_strdupa(outbound_group);   
02228       pbx_builtin_setvar_helper(chan, "OUTBOUND_GROUP_ONCE", NULL);
02229    } else if ((outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP"))) {
02230       outbound_group = ast_strdupa(outbound_group);
02231    }
02232    ast_channel_unlock(chan);
02233 
02234    /* Set per dial instance flags.  These flags are also passed back to RetryDial. */
02235    ast_copy_flags64(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID
02236       | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING | OPT_CANCEL_TIMEOUT
02237       | OPT_ANNOUNCE | OPT_CALLEE_MACRO | OPT_CALLEE_GOSUB | OPT_FORCECLID);
02238 
02239    /* loop through the list of dial destinations */
02240    rest = args.peers;
02241    while ((cur = strsep(&rest, "&")) ) {
02242       struct chanlist *tmp;
02243       struct ast_channel *tc; /* channel for this destination */
02244       /* Get a technology/[device:]number pair */
02245       char *number = cur;
02246       char *interface = ast_strdupa(number);
02247       char *tech = strsep(&number, "/");
02248       /* find if we already dialed this interface */
02249       struct ast_dialed_interface *di;
02250       AST_LIST_HEAD(, ast_dialed_interface) *dialed_interfaces;
02251       num_dialed++;
02252       if (ast_strlen_zero(number)) {
02253          ast_log(LOG_WARNING, "Dial argument takes format (technology/[device:]number1)\n");
02254          goto out;
02255       }
02256       if (!(tmp = ast_calloc(1, sizeof(*tmp))))
02257          goto out;
02258       if (opts.flags) {
02259          /* Set per outgoing call leg options. */
02260          ast_copy_flags64(tmp, &opts,
02261             OPT_CANCEL_ELSEWHERE |
02262             OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
02263             OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
02264             OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
02265             OPT_CALLEE_PARK | OPT_CALLER_PARK |
02266             OPT_CALLEE_MIXMONITOR | OPT_CALLER_MIXMONITOR |
02267             OPT_RINGBACK | OPT_MUSICBACK | OPT_FORCECLID | OPT_IGNORE_CONNECTEDLINE);
02268          ast_set2_flag64(tmp, args.url, DIAL_NOFORWARDHTML);
02269       }
02270       ast_copy_string(numsubst, number, sizeof(numsubst));
02271       /* Request the peer */
02272 
02273       ast_channel_lock(chan);
02274       datastore = ast_channel_datastore_find(chan, &dialed_interface_info, NULL);
02275       /*
02276        * Seed the chanlist's connected line information with previously
02277        * acquired connected line info from the incoming channel.  The
02278        * previously acquired connected line info could have been set
02279        * through the CONNECTED_LINE dialplan function.
02280        */
02281       ast_party_connected_line_copy(&tmp->connected, &chan->connected);
02282       ast_channel_unlock(chan);
02283 
02284       if (datastore)
02285          dialed_interfaces = datastore->data;
02286       else {
02287          if (!(datastore = ast_datastore_alloc(&dialed_interface_info, NULL))) {
02288             ast_log(LOG_WARNING, "Unable to create channel datastore for dialed interfaces. Aborting!\n");
02289             chanlist_free(tmp);
02290             goto out;
02291          }
02292 
02293          datastore->inheritance = DATASTORE_INHERIT_FOREVER;
02294 
02295          if (!(dialed_interfaces = ast_calloc(1, sizeof(*dialed_interfaces)))) {
02296             ast_datastore_free(datastore);
02297             chanlist_free(tmp);
02298             goto out;
02299          }
02300 
02301          datastore->data = dialed_interfaces;
02302          AST_LIST_HEAD_INIT(dialed_interfaces);
02303 
02304          ast_channel_lock(chan);
02305          ast_channel_datastore_add(chan, datastore);
02306          ast_channel_unlock(chan);
02307       }
02308 
02309       AST_LIST_LOCK(dialed_interfaces);
02310       AST_LIST_TRAVERSE(dialed_interfaces, di, list) {
02311          if (!strcasecmp(di->interface, interface)) {
02312             ast_log(LOG_WARNING, "Skipping dialing interface '%s' again since it has already been dialed\n",
02313                di->interface);
02314             break;
02315          }
02316       }
02317       AST_LIST_UNLOCK(dialed_interfaces);
02318 
02319       if (di) {
02320          fulldial++;
02321          chanlist_free(tmp);
02322          continue;
02323       }
02324 
02325       /* It is always ok to dial a Local interface.  We only keep track of
02326        * which "real" interfaces have been dialed.  The Local channel will
02327        * inherit this list so that if it ends up dialing a real interface,
02328        * it won't call one that has already been called. */
02329       if (strcasecmp(tech, "Local")) {
02330          if (!(di = ast_calloc(1, sizeof(*di) + strlen(interface)))) {
02331             AST_LIST_UNLOCK(dialed_interfaces);
02332             chanlist_free(tmp);
02333             goto out;
02334          }
02335          strcpy(di->interface, interface);
02336 
02337          AST_LIST_LOCK(dialed_interfaces);
02338          AST_LIST_INSERT_TAIL(dialed_interfaces, di, list);
02339          AST_LIST_UNLOCK(dialed_interfaces);
02340       }
02341 
02342       tc = ast_request(tech, chan->nativeformats, chan, numsubst, &cause);
02343       if (!tc) {
02344          /* If we can't, just go on to the next call */
02345          ast_log(LOG_WARNING, "Unable to create channel of type '%s' (cause %d - %s)\n",
02346             tech, cause, ast_cause2str(cause));
02347          handle_cause(cause, &num);
02348          if (!rest) /* we are on the last destination */
02349             chan->hangupcause = cause;
02350          chanlist_free(tmp);
02351          if (!ignore_cc && (cause == AST_CAUSE_BUSY || cause == AST_CAUSE_CONGESTION)) {
02352             if (!ast_cc_callback(chan, tech, numsubst, ast_cc_busy_interface)) {
02353                ast_cc_extension_monitor_add_dialstring(chan, interface, "");
02354             }
02355          }
02356          continue;
02357       }
02358       ast_channel_get_device_name(tc, device_name, sizeof(device_name));
02359       if (!ignore_cc) {
02360          ast_cc_extension_monitor_add_dialstring(chan, interface, device_name);
02361       }
02362       pbx_builtin_setvar_helper(tc, "DIALEDPEERNUMBER", numsubst);
02363 
02364       ast_channel_lock(tc);
02365       while (ast_channel_trylock(chan)) {
02366          CHANNEL_DEADLOCK_AVOIDANCE(tc);
02367       }
02368       /* Setup outgoing SDP to match incoming one */
02369       if (!outgoing && !rest && CAN_EARLY_BRIDGE(peerflags, chan, tc)) {
02370          ast_rtp_instance_early_bridge_make_compatible(tc, chan);
02371       }
02372       
02373       /* Inherit specially named variables from parent channel */
02374       ast_channel_inherit_variables(chan, tc);
02375       ast_channel_datastore_inherit(chan, tc);
02376 
02377       tc->appl = "AppDial";
02378       tc->data = "(Outgoing Line)";
02379       memset(&tc->whentohangup, 0, sizeof(tc->whentohangup));
02380 
02381       /* Determine CallerID to store in outgoing channel. */
02382       ast_party_caller_set_init(&caller, &tc->caller);
02383       if (ast_test_flag64(peerflags, OPT_ORIGINAL_CLID)) {
02384          caller.id = stored_clid;
02385          ast_channel_set_caller_event(tc, &caller, NULL);
02386          ast_set_flag64(tmp, DIAL_CALLERID_ABSENT);
02387       } else if (ast_strlen_zero(S_COR(tc->caller.id.number.valid,
02388          tc->caller.id.number.str, NULL))) {
02389          /*
02390           * The new channel has no preset CallerID number by the channel
02391           * driver.  Use the dialplan extension and hint name.
02392           */
02393          caller.id = stored_clid;
02394          if (!caller.id.name.valid
02395             && !ast_strlen_zero(S_COR(chan->connected.id.name.valid,
02396                chan->connected.id.name.str, NULL))) {
02397             /*
02398              * No hint name available.  We have a connected name supplied by
02399              * the dialplan we can use instead.
02400              */
02401             caller.id.name.valid = 1;
02402             caller.id.name = chan->connected.id.name;
02403          }
02404          ast_channel_set_caller_event(tc, &caller, NULL);
02405          ast_set_flag64(tmp, DIAL_CALLERID_ABSENT);
02406       } else if (ast_strlen_zero(S_COR(tc->caller.id.name.valid, tc->caller.id.name.str,
02407          NULL))) {
02408          /* The new channel has no preset CallerID name by the channel driver. */
02409          if (!ast_strlen_zero(S_COR(chan->connected.id.name.valid,
02410             chan->connected.id.name.str, NULL))) {
02411             /*
02412              * We have a connected name supplied by the dialplan we can
02413              * use instead.
02414              */
02415             caller.id.name.valid = 1;
02416             caller.id.name = chan->connected.id.name;
02417             ast_channel_set_caller_event(tc, &caller, NULL);
02418          }
02419       }
02420 
02421       /* Determine CallerID for outgoing channel to send. */
02422       if (ast_test_flag64(peerflags, OPT_FORCECLID) && !force_forwards_only) {
02423          struct ast_party_connected_line connected;
02424 
02425          ast_party_connected_line_set_init(&connected, &tc->connected);
02426          connected.id = forced_clid;
02427          ast_channel_set_connected_line(tc, &connected, NULL);
02428       } else {
02429          ast_connected_line_copy_from_caller(&tc->connected, &chan->caller);
02430       }
02431 
02432       ast_party_redirecting_copy(&tc->redirecting, &chan->redirecting);
02433 
02434       tc->dialed.transit_network_select = chan->dialed.transit_network_select;
02435 
02436       if (!ast_strlen_zero(chan->accountcode)) {
02437          ast_string_field_set(tc, accountcode, chan->accountcode);
02438       }
02439       if (ast_strlen_zero(tc->musicclass))
02440          ast_string_field_set(tc, musicclass, chan->musicclass);
02441 
02442       /* Pass ADSI CPE and transfer capability */
02443       tc->adsicpe = chan->adsicpe;
02444       tc->transfercapability = chan->transfercapability;
02445 
02446       /* If we have an outbound group, set this peer channel to it */
02447       if (outbound_group)
02448          ast_app_group_set_channel(tc, outbound_group);
02449       /* If the calling channel has the ANSWERED_ELSEWHERE flag set, inherit it. This is to support local channels */
02450       if (ast_test_flag(chan, AST_FLAG_ANSWERED_ELSEWHERE))
02451          ast_set_flag(tc, AST_FLAG_ANSWERED_ELSEWHERE);
02452 
02453       /* Check if we're forced by configuration */
02454       if (ast_test_flag64(&opts, OPT_CANCEL_ELSEWHERE))
02455           ast_set_flag(tc, AST_FLAG_ANSWERED_ELSEWHERE);
02456 
02457 
02458       /* Inherit context and extension */
02459       ast_string_field_set(tc, dialcontext, ast_strlen_zero(chan->macrocontext) ? chan->context : chan->macrocontext);
02460       if (!ast_strlen_zero(chan->macroexten))
02461          ast_copy_string(tc->exten, chan->macroexten, sizeof(tc->exten));
02462       else
02463          ast_copy_string(tc->exten, chan->exten, sizeof(tc->exten));
02464 
02465       ast_channel_unlock(tc);
02466       ast_channel_unlock(chan);
02467       res = ast_call(tc, numsubst, 0); /* Place the call, but don't wait on the answer */
02468       ast_channel_lock(chan);
02469 
02470       /* Save the info in cdr's that we called them */
02471       if (chan->cdr)
02472          ast_cdr_setdestchan(chan->cdr, tc->name);
02473 
02474       /* check the results of ast_call */
02475       if (res) {
02476          /* Again, keep going even if there's an error */
02477          ast_debug(1, "ast call on peer returned %d\n", res);
02478          ast_verb(3, "Couldn't call %s/%s\n", tech, numsubst);
02479          if (tc->hangupcause) {
02480             chan->hangupcause = tc->hangupcause;
02481          }
02482          ast_channel_unlock(chan);
02483          ast_cc_call_failed(chan, tc, interface);
02484          ast_hangup(tc);
02485          tc = NULL;
02486          chanlist_free(tmp);
02487          continue;
02488       } else {
02489          senddialevent(chan, tc, numsubst);
02490          ast_verb(3, "Called %s/%s\n", tech, numsubst);
02491          ast_channel_unlock(chan);
02492       }
02493       /* Put them in the list of outgoing thingies...  We're ready now.
02494          XXX If we're forcibly removed, these outgoing calls won't get
02495          hung up XXX */
02496       ast_set_flag64(tmp, DIAL_STILLGOING);
02497       tmp->chan = tc;
02498       tmp->next = outgoing;
02499       outgoing = tmp;
02500       /* If this line is up, don't try anybody else */
02501       if (outgoing->chan->_state == AST_STATE_UP)
02502          break;
02503    }
02504    
02505    if (ast_strlen_zero(args.timeout)) {
02506       to = -1;
02507    } else {
02508       to = atoi(args.timeout);
02509       if (to > 0)
02510          to *= 1000;
02511       else {
02512          ast_log(LOG_WARNING, "Invalid timeout specified: '%s'. Setting timeout to infinite\n", args.timeout);
02513          to = -1;
02514       }
02515    }
02516 
02517    if (!outgoing) {
02518       strcpy(pa.status, "CHANUNAVAIL");
02519       if (fulldial == num_dialed) {
02520          res = -1;
02521          goto out;
02522       }
02523    } else {
02524       /* Our status will at least be NOANSWER */
02525       strcpy(pa.status, "NOANSWER");
02526       if (ast_test_flag64(outgoing, OPT_MUSICBACK)) {
02527          moh = 1;
02528          if (!ast_strlen_zero(opt_args[OPT_ARG_MUSICBACK])) {
02529             char *original_moh = ast_strdupa(chan->musicclass);
02530             ast_string_field_set(chan, musicclass, opt_args[OPT_ARG_MUSICBACK]);
02531             ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK], NULL);
02532             ast_string_field_set(chan, musicclass, original_moh);
02533          } else {
02534             ast_moh_start(chan, NULL, NULL);
02535          }
02536          ast_indicate(chan, AST_CONTROL_PROGRESS);
02537       } else if (ast_test_flag64(outgoing, OPT_RINGBACK)) {
02538          if (!ast_strlen_zero(opt_args[OPT_ARG_RINGBACK])) {
02539             if (dial_handle_playtones(chan, opt_args[OPT_ARG_RINGBACK])){
02540                ast_indicate(chan, AST_CONTROL_RINGING);
02541                sentringing++;
02542             } else {
02543                ast_indicate(chan, AST_CONTROL_PROGRESS);
02544             }
02545          } else {
02546             ast_indicate(chan, AST_CONTROL_RINGING);
02547             sentringing++;
02548          }
02549       }
02550    }
02551 
02552    peer = wait_for_answer(chan, outgoing, &to, peerflags, opt_args, &pa, &num, &result,
02553       dtmf_progress, ignore_cc, &forced_clid, &stored_clid);
02554 
02555    /* The ast_channel_datastore_remove() function could fail here if the
02556     * datastore was moved to another channel during a masquerade. If this is
02557     * the case, don't free the datastore here because later, when the channel
02558     * to which the datastore was moved hangs up, it will attempt to free this
02559     * datastore again, causing a crash
02560     */
02561    ast_channel_lock(chan);
02562    datastore = ast_channel_datastore_find(chan, &dialed_interface_info, NULL); /* make sure we weren't cleaned up already */
02563    if (datastore && !ast_channel_datastore_remove(chan, datastore)) {
02564       ast_datastore_free(datastore);
02565    }
02566    ast_channel_unlock(chan);
02567    if (!peer) {
02568       if (result) {
02569          res = result;
02570       } else if (to) { /* Musta gotten hung up */
02571          res = -1;
02572       } else { /* Nobody answered, next please? */
02573          res = 0;
02574       }
02575    } else {
02576       const char *number;
02577 
02578       if (ast_test_flag64(&opts, OPT_CALLER_ANSWER))
02579          ast_answer(chan);
02580 
02581       strcpy(pa.status, "ANSWER");
02582       pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
02583       /* Ah ha!  Someone answered within the desired timeframe.  Of course after this
02584          we will always return with -1 so that it is hung up properly after the
02585          conversation.  */
02586       hanguptree(outgoing, peer, 1);
02587       outgoing = NULL;
02588       /* If appropriate, log that we have a destination channel and set the answer time */
02589       if (chan->cdr) {
02590          ast_cdr_setdestchan(chan->cdr, peer->name);
02591          ast_cdr_setanswer(chan->cdr, peer->cdr->answer);
02592       }
02593       if (peer->name)
02594          pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
02595       
02596       ast_channel_lock(peer);
02597       number = pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER"); 
02598       if (!number)
02599          number = numsubst;
02600       pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number);
02601       ast_channel_unlock(peer);
02602 
02603       if (!ast_strlen_zero(args.url) && ast_channel_supports_html(peer) ) {
02604          ast_debug(1, "app_dial: sendurl=%s.\n", args.url);
02605          ast_channel_sendurl( peer, args.url );
02606       }
02607       if ( (ast_test_flag64(&opts, OPT_PRIVACY) || ast_test_flag64(&opts, OPT_SCREENING)) && pa.privdb_val == AST_PRIVACY_UNKNOWN) {
02608          if (do_privacy(chan, peer, &opts, opt_args, &pa)) {
02609             res = 0;
02610             goto out;
02611          }
02612       }
02613       if (!ast_test_flag64(&opts, OPT_ANNOUNCE) || ast_strlen_zero(opt_args[OPT_ARG_ANNOUNCE])) {
02614          res = 0;
02615       } else {
02616          int digit = 0;
02617          struct ast_channel *chans[2];
02618          struct ast_channel *active_chan;
02619 
02620          chans[0] = chan;
02621          chans[1] = peer;
02622 
02623          /* we need to stream the announcment while monitoring the caller for a hangup */
02624 
02625          /* stream the file */
02626          res = ast_streamfile(peer, opt_args[OPT_ARG_ANNOUNCE], peer->language);
02627          if (res) {
02628             res = 0;
02629             ast_log(LOG_ERROR, "error streaming file '%s' to callee\n", opt_args[OPT_ARG_ANNOUNCE]);
02630          }
02631 
02632          ast_set_flag(peer, AST_FLAG_END_DTMF_ONLY);
02633          while (peer->stream) {
02634             int ms;
02635 
02636             ms = ast_sched_wait(peer->sched);
02637 
02638             if (ms < 0 && !peer->timingfunc) {
02639                ast_stopstream(peer);
02640                break;
02641             }
02642             if (ms < 0)
02643                ms = 1000;
02644 
02645             active_chan = ast_waitfor_n(chans, 2, &ms);
02646             if (active_chan) {
02647                struct ast_frame *fr = ast_read(active_chan);
02648                if (!fr) {
02649                   ast_hangup(peer);
02650                   res = -1;
02651                   goto done;
02652                }
02653                switch(fr->frametype) {
02654                   case AST_FRAME_DTMF_END:
02655                      digit = fr->subclass.integer;
02656                      if (active_chan == peer && strchr(AST_DIGIT_ANY, res)) {
02657                         ast_stopstream(peer);
02658                         res = ast_senddigit(chan, digit, 0);
02659                      }
02660                      break;
02661                   case AST_FRAME_CONTROL:
02662                      switch (fr->subclass.integer) {
02663                         case AST_CONTROL_HANGUP:
02664                            ast_frfree(fr);
02665                            ast_hangup(peer);
02666                            res = -1;
02667                            goto done;
02668                         default:
02669                            break;
02670                      }
02671                      break;
02672                   default:
02673                      /* Ignore all others */
02674                      break;
02675                }
02676                ast_frfree(fr);
02677             }
02678             ast_sched_runq(peer->sched);
02679          }
02680          ast_clear_flag(peer, AST_FLAG_END_DTMF_ONLY);
02681       }
02682 
02683       if (chan && peer && ast_test_flag64(&opts, OPT_GOTO) && !ast_strlen_zero(opt_args[OPT_ARG_GOTO])) {
02684          /* chan and peer are going into the PBX, they both
02685           * should probably get CDR records. */
02686          ast_clear_flag(chan->cdr, AST_CDR_FLAG_DIALED);
02687          ast_clear_flag(peer->cdr, AST_CDR_FLAG_DIALED);
02688 
02689          replace_macro_delimiter(opt_args[OPT_ARG_GOTO]);
02690          ast_parseable_goto(chan, opt_args[OPT_ARG_GOTO]);
02691          /* peer goes to the same context and extension as chan, so just copy info from chan*/
02692          ast_copy_string(peer->context, chan->context, sizeof(peer->context));
02693          ast_copy_string(peer->exten, chan->exten, sizeof(peer->exten));
02694          peer->priority = chan->priority + 2;
02695          if (ast_pbx_start(peer)) {
02696             ast_hangup(peer);
02697          }
02698          hanguptree(outgoing, NULL, ast_test_flag64(&opts, OPT_CANCEL_ELSEWHERE) ? 1 : 0);
02699          if (continue_exec)
02700             *continue_exec = 1;
02701          res = 0;
02702          goto done;
02703       }
02704 
02705       if (ast_test_flag64(&opts, OPT_CALLEE_MACRO) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_MACRO])) {
02706          struct ast_app *theapp;
02707          const char *macro_result;
02708 
02709          res = ast_autoservice_start(chan);
02710          if (res) {
02711             ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
02712             res = -1;
02713          }
02714 
02715          theapp = pbx_findapp("Macro");
02716 
02717          if (theapp && !res) { /* XXX why check res here ? */
02718             /* Set peer->exten and peer->context so that MACRO_EXTEN and MACRO_CONTEXT get set */
02719             ast_copy_string(peer->context, chan->context, sizeof(peer->context));
02720             ast_copy_string(peer->exten, chan->exten, sizeof(peer->exten));
02721 
02722             replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_MACRO]);
02723             res = pbx_exec(peer, theapp, opt_args[OPT_ARG_CALLEE_MACRO]);
02724             ast_debug(1, "Macro exited with status %d\n", res);
02725             res = 0;
02726          } else {
02727             ast_log(LOG_ERROR, "Could not find application Macro\n");
02728             res = -1;
02729          }
02730 
02731          if (ast_autoservice_stop(chan) < 0) {
02732             res = -1;
02733          }
02734 
02735          ast_channel_lock(peer);
02736 
02737          if (!res && (macro_result = pbx_builtin_getvar_helper(peer, "MACRO_RESULT"))) {
02738             char *macro_transfer_dest;
02739 
02740             if (!strcasecmp(macro_result, "BUSY")) {
02741                ast_copy_string(pa.status, macro_result, sizeof(pa.status));
02742                ast_set_flag64(peerflags, OPT_GO_ON);
02743                res = -1;
02744             } else if (!strcasecmp(macro_result, "CONGESTION") || !strcasecmp(macro_result, "CHANUNAVAIL")) {
02745                ast_copy_string(pa.status, macro_result, sizeof(pa.status));
02746                ast_set_flag64(peerflags, OPT_GO_ON);
02747                res = -1;
02748             } else if (!strcasecmp(macro_result, "CONTINUE")) {
02749                /* hangup peer and keep chan alive assuming the macro has changed
02750                   the context / exten / priority or perhaps
02751                   the next priority in the current exten is desired.
02752                */
02753                ast_set_flag64(peerflags, OPT_GO_ON);
02754                res = -1;
02755             } else if (!strcasecmp(macro_result, "ABORT")) {
02756                /* Hangup both ends unless the caller has the g flag */
02757                res = -1;
02758             } else if (!strncasecmp(macro_result, "GOTO:", 5) && (macro_transfer_dest = ast_strdupa(macro_result + 5))) {
02759                res = -1;
02760                /* perform a transfer to a new extension */
02761                if (strchr(macro_transfer_dest, '^')) { /* context^exten^priority*/
02762                   replace_macro_delimiter(macro_transfer_dest);
02763                }
02764                if (!ast_parseable_goto(chan, macro_transfer_dest)) {
02765                   ast_set_flag64(peerflags, OPT_GO_ON);
02766                }
02767             }
02768          }
02769 
02770          ast_channel_unlock(peer);
02771       }
02772 
02773       if (ast_test_flag64(&opts, OPT_CALLEE_GOSUB) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_GOSUB])) {
02774          struct ast_app *theapp;
02775          const char *gosub_result;
02776          char *gosub_args, *gosub_argstart;
02777          int res9 = -1;
02778 
02779          res9 = ast_autoservice_start(chan);
02780          if (res9) {
02781             ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
02782             res9 = -1;
02783          }
02784 
02785          theapp = pbx_findapp("Gosub");
02786 
02787          if (theapp && !res9) {
02788             replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_GOSUB]);
02789 
02790             /* Set where we came from */
02791             ast_copy_string(peer->context, "app_dial_gosub_virtual_context", sizeof(peer->context));
02792             ast_copy_string(peer->exten, "s", sizeof(peer->exten));
02793             peer->priority = 0;
02794 
02795             gosub_argstart = strchr(opt_args[OPT_ARG_CALLEE_GOSUB], ',');
02796             if (gosub_argstart) {
02797                const char *what_is_s = "s";
02798                *gosub_argstart = 0;
02799                if (!ast_exists_extension(peer, opt_args[OPT_ARG_CALLEE_GOSUB], "s", 1, S_COR(peer->caller.id.number.valid, peer->caller.id.number.str, NULL)) &&
02800                    ast_exists_extension(peer, opt_args[OPT_ARG_CALLEE_GOSUB], "~~s~~", 1, S_COR(peer->caller.id.number.valid, peer->caller.id.number.str, NULL))) {
02801                   what_is_s = "~~s~~";
02802                }
02803                if (ast_asprintf(&gosub_args, "%s,%s,1(%s)", opt_args[OPT_ARG_CALLEE_GOSUB], what_is_s, gosub_argstart + 1) < 0) {
02804                   gosub_args = NULL;
02805                }
02806                *gosub_argstart = ',';
02807             } else {
02808                const char *what_is_s = "s";
02809                if (!ast_exists_extension(peer, opt_args[OPT_ARG_CALLEE_GOSUB], "s", 1, S_COR(peer->caller.id.number.valid, peer->caller.id.number.str, NULL)) &&
02810                    ast_exists_extension(peer, opt_args[OPT_ARG_CALLEE_GOSUB], "~~s~~", 1, S_COR(peer->caller.id.number.valid, peer->caller.id.number.str, NULL))) {
02811                   what_is_s = "~~s~~";
02812                }
02813                if (ast_asprintf(&gosub_args, "%s,%s,1", opt_args[OPT_ARG_CALLEE_GOSUB], what_is_s) < 0) {
02814                   gosub_args = NULL;
02815                }
02816             }
02817 
02818             if (gosub_args) {
02819                res9 = pbx_exec(peer, theapp, gosub_args);
02820                if (!res9) {
02821                   struct ast_pbx_args args;
02822                   /* A struct initializer fails to compile for this case ... */
02823                   memset(&args, 0, sizeof(args));
02824                   args.no_hangup_chan = 1;
02825                   ast_pbx_run_args(peer, &args);
02826                }
02827                ast_free(gosub_args);
02828                ast_debug(1, "Gosub exited with status %d\n", res9);
02829             } else {
02830                ast_log(LOG_ERROR, "Could not Allocate string for Gosub arguments -- Gosub Call Aborted!\n");
02831             }
02832 
02833          } else if (!res9) {
02834             ast_log(LOG_ERROR, "Could not find application Gosub\n");
02835             res9 = -1;
02836          }
02837 
02838          if (ast_autoservice_stop(chan) < 0) {
02839             res9 = -1;
02840          }
02841          
02842          ast_channel_lock(peer);
02843 
02844          if (!res9 && (gosub_result = pbx_builtin_getvar_helper(peer, "GOSUB_RESULT"))) {
02845             char *gosub_transfer_dest;
02846             const char *gosub_retval = pbx_builtin_getvar_helper(peer, "GOSUB_RETVAL");
02847 
02848             /* Inherit return value from the peer, so it can be used in the master */
02849             if (gosub_retval) {
02850                pbx_builtin_setvar_helper(chan, "GOSUB_RETVAL", gosub_retval);
02851             }
02852 
02853             if (!strcasecmp(gosub_result, "BUSY")) {
02854                ast_copy_string(pa.status, gosub_result, sizeof(pa.status));
02855                ast_set_flag64(peerflags, OPT_GO_ON);
02856                res = -1;
02857             } else if (!strcasecmp(gosub_result, "CONGESTION") || !strcasecmp(gosub_result, "CHANUNAVAIL")) {
02858                ast_copy_string(pa.status, gosub_result, sizeof(pa.status));
02859                ast_set_flag64(peerflags, OPT_GO_ON);
02860                res = -1;
02861             } else if (!strcasecmp(gosub_result, "CONTINUE")) {
02862                /* hangup peer and keep chan alive assuming the macro has changed
02863                   the context / exten / priority or perhaps
02864                   the next priority in the current exten is desired.
02865                */
02866                ast_set_flag64(peerflags, OPT_GO_ON);
02867                res = -1;
02868             } else if (!strcasecmp(gosub_result, "ABORT")) {
02869                /* Hangup both ends unless the caller has the g flag */
02870                res = -1;
02871             } else if (!strncasecmp(gosub_result, "GOTO:", 5) && (gosub_transfer_dest = ast_strdupa(gosub_result + 5))) {
02872                res = -1;
02873                /* perform a transfer to a new extension */
02874                if (strchr(gosub_transfer_dest, '^')) { /* context^exten^priority*/
02875                   replace_macro_delimiter(gosub_transfer_dest);
02876                }
02877                if (!ast_parseable_goto(chan, gosub_transfer_dest)) {
02878                   ast_set_flag64(peerflags, OPT_GO_ON);
02879                }
02880             }
02881          }
02882 
02883          ast_channel_unlock(peer);  
02884       }
02885 
02886       if (!res) {
02887          if (!ast_tvzero(calldurationlimit)) {
02888             struct timeval whentohangup = calldurationlimit;
02889             peer->whentohangup = ast_tvadd(ast_tvnow(), whentohangup);
02890          }
02891          if (!ast_strlen_zero(dtmfcalled)) {
02892             ast_verb(3, "Sending DTMF '%s' to the called party.\n", dtmfcalled);
02893             res = ast_dtmf_stream(peer, chan, dtmfcalled, 250, 0);
02894          }
02895          if (!ast_strlen_zero(dtmfcalling)) {
02896             ast_verb(3, "Sending DTMF '%s' to the calling party.\n", dtmfcalling);
02897             res = ast_dtmf_stream(chan, peer, dtmfcalling, 250, 0);
02898          }
02899       }
02900 
02901       if (res) { /* some error */
02902          res = -1;
02903       } else {
02904          if (ast_test_flag64(peerflags, OPT_CALLEE_TRANSFER))
02905             ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
02906          if (ast_test_flag64(peerflags, OPT_CALLER_TRANSFER))
02907             ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
02908          if (ast_test_flag64(peerflags, OPT_CALLEE_HANGUP))
02909             ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
02910          if (ast_test_flag64(peerflags, OPT_CALLER_HANGUP))
02911             ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
02912          if (ast_test_flag64(peerflags, OPT_CALLEE_MONITOR))
02913             ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
02914          if (ast_test_flag64(peerflags, OPT_CALLER_MONITOR))
02915             ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
02916          if (ast_test_flag64(peerflags, OPT_CALLEE_PARK))
02917             ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
02918          if (ast_test_flag64(peerflags, OPT_CALLER_PARK))
02919             ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
02920          if (ast_test_flag64(peerflags, OPT_CALLEE_MIXMONITOR))
02921             ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMIXMON);
02922          if (ast_test_flag64(peerflags, OPT_CALLER_MIXMONITOR))
02923             ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMIXMON);
02924          if (ast_test_flag64(peerflags, OPT_GO_ON))
02925             ast_set_flag(&(config.features_caller), AST_FEATURE_NO_H_EXTEN);
02926 
02927          config.end_bridge_callback = end_bridge_callback;
02928          config.end_bridge_callback_data = chan;
02929          config.end_bridge_callback_data_fixup = end_bridge_callback_data_fixup;
02930          
02931          if (moh) {
02932             moh = 0;
02933             ast_moh_stop(chan);
02934          } else if (sentringing) {
02935             sentringing = 0;
02936             ast_indicate(chan, -1);
02937          }
02938          /* Be sure no generators are left on it and reset the visible indication */
02939          ast_deactivate_generator(chan);
02940          chan->visible_indication = 0;
02941          /* Make sure channels are compatible */
02942          res = ast_channel_make_compatible(chan, peer);
02943          if (res < 0) {
02944             ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
02945             ast_hangup(peer);
02946             res = -1;
02947             goto done;
02948          }
02949          if (opermode) {
02950             struct oprmode oprmode;
02951 
02952             oprmode.peer = peer;
02953             oprmode.mode = opermode;
02954 
02955             ast_channel_setoption(chan, AST_OPTION_OPRMODE, &oprmode, sizeof(oprmode), 0);
02956          }
02957          res = ast_bridge_call(chan, peer, &config);
02958       }
02959 
02960       strcpy(peer->context, chan->context);
02961 
02962       if (ast_test_flag64(&opts, OPT_PEER_H)
02963          && ast_exists_extension(peer, peer->context, "h", 1,
02964             S_COR(peer->caller.id.number.valid, peer->caller.id.number.str, NULL))) {
02965          int autoloopflag;
02966          int found;
02967          int res9;
02968          
02969          strcpy(peer->exten, "h");
02970          peer->priority = 1;
02971          autoloopflag = ast_test_flag(peer, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */
02972          ast_set_flag(peer, AST_FLAG_IN_AUTOLOOP);
02973 
02974          while ((res9 = ast_spawn_extension(peer, peer->context, peer->exten,
02975             peer->priority,
02976             S_COR(peer->caller.id.number.valid, peer->caller.id.number.str, NULL),
02977             &found, 1)) == 0) {
02978             peer->priority++;
02979          }
02980 
02981          if (found && res9) {
02982             /* Something bad happened, or a hangup has been requested. */
02983             ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", peer->context, peer->exten, peer->priority, peer->name);
02984             ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", peer->context, peer->exten, peer->priority, peer->name);
02985          }
02986          ast_set2_flag(peer, autoloopflag, AST_FLAG_IN_AUTOLOOP);  /* set it back the way it was */
02987       }
02988       if (!ast_check_hangup(peer)) {
02989          if (ast_test_flag64(&opts, OPT_CALLEE_GO_ON)) {
02990             int goto_res;
02991 
02992             if (!ast_strlen_zero(opt_args[OPT_ARG_CALLEE_GO_ON])) {
02993                replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_GO_ON]);
02994                goto_res = ast_parseable_goto(peer, opt_args[OPT_ARG_CALLEE_GO_ON]);
02995             } else { /* F() */
02996                goto_res = ast_goto_if_exists(peer, chan->context,
02997                   chan->exten, chan->priority + 1);
02998             }
02999             if (!goto_res && !ast_pbx_start(peer)) {
03000                /* The peer is now running its own PBX. */
03001                goto out;
03002             }
03003          }
03004       } else if (!ast_check_hangup(chan)) {
03005          chan->hangupcause = peer->hangupcause;
03006       }
03007       ast_hangup(peer);
03008    }
03009 out:
03010    if (moh) {
03011       moh = 0;
03012       ast_moh_stop(chan);
03013    } else if (sentringing) {
03014       sentringing = 0;
03015       ast_indicate(chan, -1);
03016    }
03017 
03018    if (delprivintro && ast_fileexists(pa.privintro, NULL, NULL) > 0) {
03019       ast_filedelete(pa.privintro, NULL);
03020       if (ast_fileexists(pa.privintro, NULL, NULL) > 0) {
03021          ast_log(LOG_NOTICE, "privacy: ast_filedelete didn't do its job on %s\n", pa.privintro);
03022       } else {
03023          ast_verb(3, "Successfully deleted %s intro file\n", pa.privintro);
03024       }
03025    }
03026 
03027    ast_channel_early_bridge(chan, NULL);
03028    /* When dialing local channels, the hangupcause of the parent channel
03029     * tells us whether the call was answered elsewhere. */
03030    hanguptree(outgoing, NULL, chan->hangupcause == AST_CAUSE_ANSWERED_ELSEWHERE ? 1 : 0);
03031    pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
03032    senddialendevent(chan, pa.status);
03033    ast_debug(1, "Exiting with DIALSTATUS=%s (HANGUPCAUSE=%d).\n", pa.status, chan->hangupcause);
03034    
03035    if ((ast_test_flag64(peerflags, OPT_GO_ON)) && !ast_check_hangup(chan) && (res != AST_PBX_INCOMPLETE)) {
03036       if (!ast_tvzero(calldurationlimit))
03037          memset(&chan->whentohangup, 0, sizeof(chan->whentohangup));
03038       res = 0;
03039    }
03040 
03041 done:
03042    if (config.warning_sound) {
03043       ast_free((char *)config.warning_sound);
03044    }
03045    if (config.end_sound) {
03046       ast_free((char *)config.end_sound);
03047    }
03048    if (config.start_sound) {
03049       ast_free((char *)config.start_sound);
03050    }
03051    ast_ignore_cc(chan);
03052    return res;
03053 }

static int dial_handle_playtones ( struct ast_channel chan,
const char *  data 
) [static]

Definition at line 1957 of file app_dial.c.

References ast_debug, ast_get_indication_tone(), ast_log(), ast_playtones_start(), ast_strlen_zero(), ast_tone_zone_sound_unref(), ast_tone_zone_sound::data, LOG_WARNING, str, and ast_channel::zone.

Referenced by dial_exec_full().

01958 {
01959    struct ast_tone_zone_sound *ts = NULL;
01960    int res;
01961    const char *str = data;
01962 
01963    if (ast_strlen_zero(str)) {
01964       ast_debug(1,"Nothing to play\n");
01965       return -1;
01966    }
01967 
01968    ts = ast_get_indication_tone(chan->zone, str);
01969 
01970    if (ts && ts->data[0]) {
01971       res = ast_playtones_start(chan, 0, ts->data, 0);
01972    } else {
01973       res = -1;
01974    }
01975 
01976    if (ts) {
01977       ts = ast_tone_zone_sound_unref(ts);
01978    }
01979 
01980    if (res) {
01981       ast_log(LOG_WARNING, "Unable to start playtone \'%s\'\n", str);
01982    }
01983 
01984    return res;
01985 }

static void do_forward ( struct chanlist o,
struct cause_args num,
struct ast_flags64 peerflags,
int  single,
int  caller_entertained,
int *  to,
struct ast_party_id forced_clid,
struct ast_party_id stored_clid 
) [static]

helper function for wait_for_answer()

Parameters:
o Outgoing call channel list.
num Incoming call channel cause accumulation
peerflags Dial option flags
single TRUE if there is only one outgoing call.
caller_entertained TRUE if the caller is being entertained by MOH or ringback.
to Remaining call timeout time.
forced_clid OPT_FORCECLID caller id to send
stored_clid Caller id representing the called party if needed

XXX this code is highly suspicious, as it essentially overwrites the outgoing channel without properly deleting it.

Todo:
eventually this function should be intergrated into and replaced by ast_call_forward()

Definition at line 837 of file app_dial.c.

References accountcode, ast_channel::appl, ast_call(), AST_CAUSE_BUSY, AST_CEL_FORWARD, ast_cel_report_event(), ast_channel_datastore_inherit(), ast_channel_inherit_variables(), ast_channel_lock, ast_channel_lock_both, ast_channel_make_compatible(), ast_channel_redirecting_macro(), ast_channel_set_caller_event(), ast_channel_unlock, ast_channel_update_redirecting(), ast_clear_flag64, ast_connected_line_copy_from_caller(), ast_copy_string(), ast_hangup(), ast_ignore_cc(), ast_indicate(), ast_log(), ast_party_caller_set_init(), ast_party_connected_line_copy(), ast_party_connected_line_init(), ast_party_number_free(), ast_party_number_init(), ast_party_redirecting_copy(), ast_party_redirecting_free(), ast_party_redirecting_init(), ast_request(), ast_rtp_instance_early_bridge_make_compatible(), ast_set_flag64, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_test_flag64, ast_verb, ast_channel::caller, CAN_EARLY_BRIDGE, cause_args::chan, chanlist::chan, ast_channel::connected, ast_channel::context, ast_channel::data, DIAL_CALLERID_ABSENT, DIAL_STILLGOING, ast_channel::dialed, ast_channel::exten, ast_party_redirecting::from, handle_cause(), ast_party_connected_line::id, ast_party_caller::id, LOG_NOTICE, ast_channel::macroexten, ast_channel::nativeformats, cause_args::nochan, ast_party_id::number, OPT_CANCEL_TIMEOUT, OPT_FORCECLID, OPT_IGNORE_CONNECTEDLINE, OPT_IGNORE_FORWARDING, OPT_ORIGINAL_CLID, pbx_builtin_getvar_helper(), ast_channel::redirecting, S_COR, S_OR, senddialevent(), ast_party_number::str, ast_channel::tech, ast_party_dialed::transit_network_select, and ast_party_number::valid.

Referenced by wait_for_answer().

00840 {
00841    char tmpchan[256];
00842    struct ast_channel *original = o->chan;
00843    struct ast_channel *c = o->chan; /* the winner */
00844    struct ast_channel *in = num->chan; /* the input channel */
00845    char *stuff;
00846    char *tech;
00847    int cause;
00848    struct ast_party_caller caller;
00849 
00850    ast_copy_string(tmpchan, c->call_forward, sizeof(tmpchan));
00851    if ((stuff = strchr(tmpchan, '/'))) {
00852       *stuff++ = '\0';
00853       tech = tmpchan;
00854    } else {
00855       const char *forward_context;
00856       ast_channel_lock(c);
00857       forward_context = pbx_builtin_getvar_helper(c, "FORWARD_CONTEXT");
00858       if (ast_strlen_zero(forward_context)) {
00859          forward_context = NULL;
00860       }
00861       snprintf(tmpchan, sizeof(tmpchan), "%s@%s", c->call_forward, forward_context ? forward_context : c->context);
00862       ast_channel_unlock(c);
00863       stuff = tmpchan;
00864       tech = "Local";
00865    }
00866    if (!strcasecmp(tech, "Local")) {
00867       /*
00868        * Drop the connected line update block for local channels since
00869        * this is going to run dialplan and the user can change his
00870        * mind about what connected line information he wants to send.
00871        */
00872       ast_clear_flag64(o, OPT_IGNORE_CONNECTEDLINE);
00873    }
00874 
00875    ast_cel_report_event(in, AST_CEL_FORWARD, NULL, c->call_forward, NULL);
00876 
00877    /* Before processing channel, go ahead and check for forwarding */
00878    ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, c->name);
00879    /* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */
00880    if (ast_test_flag64(peerflags, OPT_IGNORE_FORWARDING)) {
00881       ast_verb(3, "Forwarding %s to '%s/%s' prevented.\n", in->name, tech, stuff);
00882       c = o->chan = NULL;
00883       cause = AST_CAUSE_BUSY;
00884    } else {
00885       /* Setup parameters */
00886       c = o->chan = ast_request(tech, in->nativeformats, in, stuff, &cause);
00887       if (c) {
00888          if (single && !caller_entertained) {
00889             ast_channel_make_compatible(o->chan, in);
00890          }
00891          ast_channel_lock_both(in, o->chan);
00892          ast_channel_inherit_variables(in, o->chan);
00893          ast_channel_datastore_inherit(in, o->chan);
00894          ast_channel_unlock(in);
00895          ast_channel_unlock(o->chan);
00896          /* When a call is forwarded, we don't want to track new interfaces
00897           * dialed for CC purposes. Setting the done flag will ensure that
00898           * any Dial operations that happen later won't record CC interfaces.
00899           */
00900          ast_ignore_cc(o->chan);
00901          ast_log(LOG_NOTICE, "Not accepting call completion offers from call-forward recipient %s\n", o->chan->name);
00902       } else
00903          ast_log(LOG_NOTICE,
00904             "Forwarding failed to create channel to dial '%s/%s' (cause = %d)\n",
00905             tech, stuff, cause);
00906    }
00907    if (!c) {
00908       ast_clear_flag64(o, DIAL_STILLGOING);
00909       handle_cause(cause, num);
00910       ast_hangup(original);
00911    } else {
00912       ast_channel_lock_both(c, original);
00913       ast_party_redirecting_copy(&c->redirecting, &original->redirecting);
00914       ast_channel_unlock(c);
00915       ast_channel_unlock(original);
00916 
00917       ast_channel_lock_both(c, in);
00918 
00919       if (single && !caller_entertained && CAN_EARLY_BRIDGE(peerflags, c, in)) {
00920          ast_rtp_instance_early_bridge_make_compatible(c, in);
00921       }
00922 
00923       if (!c->redirecting.from.number.valid
00924          || ast_strlen_zero(c->redirecting.from.number.str)) {
00925          /*
00926           * The call was not previously redirected so it is
00927           * now redirected from this number.
00928           */
00929          ast_party_number_free(&c->redirecting.from.number);
00930          ast_party_number_init(&c->redirecting.from.number);
00931          c->redirecting.from.number.valid = 1;
00932          c->redirecting.from.number.str =
00933             ast_strdup(S_OR(in->macroexten, in->exten));
00934       }
00935 
00936       c->dialed.transit_network_select = in->dialed.transit_network_select;
00937 
00938       /* Determine CallerID to store in outgoing channel. */
00939       ast_party_caller_set_init(&caller, &c->caller);
00940       if (ast_test_flag64(peerflags, OPT_ORIGINAL_CLID)) {
00941          caller.id = *stored_clid;
00942          ast_channel_set_caller_event(c, &caller, NULL);
00943          ast_set_flag64(o, DIAL_CALLERID_ABSENT);
00944       } else if (ast_strlen_zero(S_COR(c->caller.id.number.valid,
00945          c->caller.id.number.str, NULL))) {
00946          /*
00947           * The new channel has no preset CallerID number by the channel
00948           * driver.  Use the dialplan extension and hint name.
00949           */
00950          caller.id = *stored_clid;
00951          ast_channel_set_caller_event(c, &caller, NULL);
00952          ast_set_flag64(o, DIAL_CALLERID_ABSENT);
00953       } else {
00954          ast_clear_flag64(o, DIAL_CALLERID_ABSENT);
00955       }
00956 
00957       /* Determine CallerID for outgoing channel to send. */
00958       if (ast_test_flag64(o, OPT_FORCECLID)) {
00959          struct ast_party_connected_line connected;
00960 
00961          ast_party_connected_line_init(&connected);
00962          connected.id = *forced_clid;
00963          ast_party_connected_line_copy(&c->connected, &connected);
00964       } else {
00965          ast_connected_line_copy_from_caller(&c->connected, &in->caller);
00966       }
00967 
00968       ast_string_field_set(c, accountcode, in->accountcode);
00969 
00970       c->appl = "AppDial";
00971       c->data = "(Outgoing Line)";
00972 
00973       ast_channel_unlock(in);
00974       if (single && !ast_test_flag64(o, OPT_IGNORE_CONNECTEDLINE)) {
00975          struct ast_party_redirecting redirecting;
00976 
00977          /*
00978           * Redirecting updates to the caller make sense only on single
00979           * calls.
00980           *
00981           * We must unlock c before calling
00982           * ast_channel_redirecting_macro, because we put c into
00983           * autoservice there.  That is pretty much a guaranteed
00984           * deadlock.  This is why the handling of c's lock may seem a
00985           * bit unusual here.
00986           */
00987          ast_party_redirecting_init(&redirecting);
00988          ast_party_redirecting_copy(&redirecting, &c->redirecting);
00989          ast_channel_unlock(c);
00990          if (ast_channel_redirecting_macro(c, in, &redirecting, 1, 0)) {
00991             ast_channel_update_redirecting(in, &redirecting, NULL);
00992          }
00993          ast_party_redirecting_free(&redirecting);
00994       } else {
00995          ast_channel_unlock(c);
00996       }
00997 
00998       if (ast_test_flag64(peerflags, OPT_CANCEL_TIMEOUT)) {
00999          *to = -1;
01000       }
01001 
01002       if (ast_call(c, stuff, 0)) {
01003          ast_log(LOG_NOTICE, "Forwarding failed to dial '%s/%s'\n",
01004             tech, stuff);
01005          ast_clear_flag64(o, DIAL_STILLGOING);
01006          ast_hangup(original);
01007          ast_hangup(c);
01008          c = o->chan = NULL;
01009          num->nochan++;
01010       } else {
01011          ast_channel_lock_both(c, in);
01012          senddialevent(in, c, stuff);
01013          ast_channel_unlock(in);
01014          ast_channel_unlock(c);
01015          /* Hangup the original channel now, in case we needed it */
01016          ast_hangup(original);
01017       }
01018       if (single && !caller_entertained) {
01019          ast_indicate(in, -1);
01020       }
01021    }
01022 }

static void end_bridge_callback ( void *  data  )  [static]

Definition at line 1928 of file app_dial.c.

References ast_cdr::answer, ast_channel_lock, ast_channel_unlock, ast_channel::cdr, pbx_builtin_setvar_helper(), and ast_cdr::start.

Referenced by dial_exec_full().

01929 {
01930    char buf[80];
01931    time_t end;
01932    struct ast_channel *chan = data;
01933 
01934    if (!chan->cdr) {
01935       return;
01936    }
01937 
01938    time(&end);
01939 
01940    ast_channel_lock(chan);
01941    if (chan->cdr->answer.tv_sec) {
01942       snprintf(buf, sizeof(buf), "%ld", (long) end - chan->cdr->answer.tv_sec);
01943       pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", buf);
01944    }
01945 
01946    if (chan->cdr->start.tv_sec) {
01947       snprintf(buf, sizeof(buf), "%ld", (long) end - chan->cdr->start.tv_sec);
01948       pbx_builtin_setvar_helper(chan, "DIALEDTIME", buf);
01949    }
01950    ast_channel_unlock(chan);
01951 }

static void end_bridge_callback_data_fixup ( struct ast_bridge_config bconfig,
struct ast_channel originator,
struct ast_channel terminator 
) [static]

Definition at line 1953 of file app_dial.c.

References ast_bridge_config::end_bridge_callback_data.

Referenced by dial_exec_full().

01953                                                                                                                                               {
01954    bconfig->end_bridge_callback_data = originator;
01955 }

static const char* get_cid_name ( char *  name,
int  namelen,
struct ast_channel chan 
) [static]

Definition at line 774 of file app_dial.c.

References ast_channel_lock, ast_channel_unlock, ast_get_hint(), ast_strdupa, ast_channel::context, context, ast_channel::exten, exten, ast_channel::macrocontext, ast_channel::macroexten, and S_OR.

Referenced by dial_exec_full().

00775 {
00776    const char *context;
00777    const char *exten;
00778 
00779    ast_channel_lock(chan);
00780    context = ast_strdupa(S_OR(chan->macrocontext, chan->context));
00781    exten = ast_strdupa(S_OR(chan->macroexten, chan->exten));
00782    ast_channel_unlock(chan);
00783 
00784    return ast_get_hint(NULL, 0, name, namelen, chan, context, exten) ? name : "";
00785 }

static void handle_cause ( int  cause,
struct cause_args num 
) [static]

Definition at line 717 of file app_dial.c.

References AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, AST_CAUSE_NO_ANSWER, AST_CAUSE_NO_ROUTE_DESTINATION, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_UNREGISTERED, ast_cdr_busy(), ast_cdr_failed(), ast_cdr_noanswer(), cause_args::busy, ast_channel::cdr, cause_args::chan, cause_args::congestion, and cause_args::nochan.

Referenced by dial_exec_full(), do_forward(), and wait_for_answer().

00718 {
00719    struct ast_cdr *cdr = num->chan->cdr;
00720 
00721    switch(cause) {
00722    case AST_CAUSE_BUSY:
00723       if (cdr)
00724          ast_cdr_busy(cdr);
00725       num->busy++;
00726       break;
00727 
00728    case AST_CAUSE_CONGESTION:
00729       if (cdr)
00730          ast_cdr_failed(cdr);
00731       num->congestion++;
00732       break;
00733 
00734    case AST_CAUSE_NO_ROUTE_DESTINATION:
00735    case AST_CAUSE_UNREGISTERED:
00736       if (cdr)
00737          ast_cdr_failed(cdr);
00738       num->nochan++;
00739       break;
00740 
00741    case AST_CAUSE_NO_ANSWER:
00742       if (cdr) {
00743          ast_cdr_noanswer(cdr);
00744       }
00745       break;
00746    case AST_CAUSE_NORMAL_CLEARING:
00747       break;
00748 
00749    default:
00750       num->nochan++;
00751       break;
00752    }
00753 }

static void hanguptree ( struct chanlist outgoing,
struct ast_channel exception,
int  answered_elsewhere 
) [static]

Definition at line 684 of file app_dial.c.

References AST_CAUSE_ANSWERED_ELSEWHERE, AST_FLAG_ANSWERED_ELSEWHERE, ast_hangup(), ast_set_flag, chanlist::chan, chanlist_free(), ast_channel::hangupcause, and chanlist::next.

Referenced by dial_exec_full().

00685 {
00686    /* Hang up a tree of stuff */
00687    struct chanlist *oo;
00688    while (outgoing) {
00689       /* Hangup any existing lines we have open */
00690       if (outgoing->chan && (outgoing->chan != exception)) {
00691          if (answered_elsewhere) {
00692             /* The flag is used for local channel inheritance and stuff */
00693             ast_set_flag(outgoing->chan, AST_FLAG_ANSWERED_ELSEWHERE);
00694             /* This is for the channel drivers */
00695             outgoing->chan->hangupcause = AST_CAUSE_ANSWERED_ELSEWHERE;
00696          }
00697          ast_hangup(outgoing->chan);
00698       }
00699       oo = outgoing;
00700       outgoing = outgoing->next;
00701       chanlist_free(oo);
00702    }
00703 }

static int load_module ( void   )  [static]

Definition at line 3188 of file app_dial.c.

References ast_add_extension2(), ast_context_find_or_create(), ast_free_ptr(), ast_log(), ast_register_application_xml, ast_strdup, dial_exec(), LOG_ERROR, and retrydial_exec().

03189 {
03190    int res;
03191    struct ast_context *con;
03192 
03193    con = ast_context_find_or_create(NULL, NULL, "app_dial_gosub_virtual_context", "app_dial");
03194    if (!con)
03195       ast_log(LOG_ERROR, "Dial virtual context 'app_dial_gosub_virtual_context' does not exist and unable to create\n");
03196    else
03197       ast_add_extension2(con, 1, "s", 1, NULL, NULL, "NoOp", ast_strdup(""), ast_free_ptr, "app_dial");
03198 
03199    res = ast_register_application_xml(app, dial_exec);
03200    res |= ast_register_application_xml(rapp, retrydial_exec);
03201 
03202    return res;
03203 }

static int onedigit_goto ( struct ast_channel chan,
const char *  context,
char  exten,
int  pri 
) [static]

Definition at line 755 of file app_dial.c.

References ast_goto_if_exists(), ast_strlen_zero(), ast_channel::context, and ast_channel::macrocontext.

Referenced by retrydial_exec(), and wait_for_answer().

00756 {
00757    char rexten[2] = { exten, '\0' };
00758 
00759    if (context) {
00760       if (!ast_goto_if_exists(chan, context, rexten, pri))
00761          return 1;
00762    } else {
00763       if (!ast_goto_if_exists(chan, chan->context, rexten, pri))
00764          return 1;
00765       else if (!ast_strlen_zero(chan->macrocontext)) {
00766          if (!ast_goto_if_exists(chan, chan->macrocontext, rexten, pri))
00767             return 1;
00768       }
00769    }
00770    return 0;
00771 }

static void replace_macro_delimiter ( char *  s  )  [static]

Definition at line 1672 of file app_dial.c.

Referenced by dial_exec_full().

01673 {
01674    for (; *s; s++)
01675       if (*s == '^')
01676          *s = ',';
01677 }

static int retrydial_exec ( struct ast_channel chan,
const char *  data 
) [static]

Definition at line 3064 of file app_dial.c.

References args, AST_APP_ARG, ast_channel_lock, ast_channel_unlock, AST_DECLARE_APP_ARGS, AST_DIGIT_ANY, ast_fileexists(), AST_FLAG_MOH, ast_log(), ast_moh_start(), ast_moh_stop(), AST_PBX_INCOMPLETE, AST_STANDARD_APP_ARGS, ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_test_flag64, ast_waitfordigit(), ast_waitstream(), context, ast_channel::data, dial_exec_full(), LOG_ERROR, LOG_WARNING, onedigit_goto(), OPT_DTMF_EXIT, parse(), and pbx_builtin_getvar_helper().

Referenced by load_module().

03065 {
03066    char *parse;
03067    const char *context = NULL;
03068    int sleepms = 0, loops = 0, res = -1;
03069    struct ast_flags64 peerflags = { 0, };
03070    AST_DECLARE_APP_ARGS(args,
03071       AST_APP_ARG(announce);
03072       AST_APP_ARG(sleep);
03073       AST_APP_ARG(retries);
03074       AST_APP_ARG(dialdata);
03075    );
03076 
03077    if (ast_strlen_zero(data)) {
03078       ast_log(LOG_WARNING, "RetryDial requires an argument!\n");
03079       return -1;
03080    }
03081 
03082    parse = ast_strdupa(data);
03083    AST_STANDARD_APP_ARGS(args, parse);
03084 
03085    if (!ast_strlen_zero(args.sleep) && (sleepms = atoi(args.sleep)))
03086       sleepms *= 1000;
03087 
03088    if (!ast_strlen_zero(args.retries)) {
03089       loops = atoi(args.retries);
03090    }
03091 
03092    if (!args.dialdata) {
03093       ast_log(LOG_ERROR, "%s requires a 4th argument (dialdata)\n", rapp);
03094       goto done;
03095    }
03096 
03097    if (sleepms < 1000)
03098       sleepms = 10000;
03099 
03100    if (!loops)
03101       loops = -1; /* run forever */
03102 
03103    ast_channel_lock(chan);
03104    context = pbx_builtin_getvar_helper(chan, "EXITCONTEXT");
03105    context = !ast_strlen_zero(context) ? ast_strdupa(context) : NULL;
03106    ast_channel_unlock(chan);
03107 
03108    res = 0;
03109    while (loops) {
03110       int continue_exec;
03111 
03112       chan->data = "Retrying";
03113       if (ast_test_flag(chan, AST_FLAG_MOH))
03114          ast_moh_stop(chan);
03115 
03116       res = dial_exec_full(chan, args.dialdata, &peerflags, &continue_exec);
03117       if (continue_exec)
03118          break;
03119 
03120       if (res == 0) {
03121          if (ast_test_flag64(&peerflags, OPT_DTMF_EXIT)) {
03122             if (!ast_strlen_zero(args.announce)) {
03123                if (ast_fileexists(args.announce, NULL, chan->language) > 0) {
03124                   if (!(res = ast_streamfile(chan, args.announce, chan->language)))
03125                      ast_waitstream(chan, AST_DIGIT_ANY);
03126                } else
03127                   ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", args.announce);
03128             }
03129             if (!res && sleepms) {
03130                if (!ast_test_flag(chan, AST_FLAG_MOH))
03131                   ast_moh_start(chan, NULL, NULL);
03132                res = ast_waitfordigit(chan, sleepms);
03133             }
03134          } else {
03135             if (!ast_strlen_zero(args.announce)) {
03136                if (ast_fileexists(args.announce, NULL, chan->language) > 0) {
03137                   if (!(res = ast_streamfile(chan, args.announce, chan->language)))
03138                      res = ast_waitstream(chan, "");
03139                } else
03140                   ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", args.announce);
03141             }
03142             if (sleepms) {
03143                if (!ast_test_flag(chan, AST_FLAG_MOH))
03144                   ast_moh_start(chan, NULL, NULL);
03145                if (!res)
03146                   res = ast_waitfordigit(chan, sleepms);
03147             }
03148          }
03149       }
03150 
03151       if (res < 0 || res == AST_PBX_INCOMPLETE) {
03152          break;
03153       } else if (res > 0) { /* Trying to send the call elsewhere (1 digit ext) */
03154          if (onedigit_goto(chan, context, (char) res, 1)) {
03155             res = 0;
03156             break;
03157          }
03158       }
03159       loops--;
03160    }
03161    if (loops == 0)
03162       res = 0;
03163    else if (res == 1)
03164       res = 0;
03165 
03166    if (ast_test_flag(chan, AST_FLAG_MOH))
03167       ast_moh_stop(chan);
03168  done:
03169    return res;
03170 }

static void senddialendevent ( struct ast_channel src,
const char *  dialstatus 
) [static]

Definition at line 810 of file app_dial.c.

References ast_manager_event, and EVENT_FLAG_CALL.

Referenced by dial_exec_full().

00811 {
00812    ast_manager_event(src, EVENT_FLAG_CALL, "Dial",
00813       "SubEvent: End\r\n"
00814       "Channel: %s\r\n"
00815       "UniqueID: %s\r\n"
00816       "DialStatus: %s\r\n",
00817       src->name, src->uniqueid, dialstatus);
00818 }

static void senddialevent ( struct ast_channel src,
struct ast_channel dst,
const char *  dialstring 
) [static]

Definition at line 787 of file app_dial.c.

References ast_manager_event_multichan, ast_channel::caller, ast_channel::connected, EVENT_FLAG_CALL, ast_party_connected_line::id, ast_party_caller::id, ast_party_id::name, ast_party_id::number, S_COR, ast_party_name::str, ast_party_number::str, ast_party_name::valid, and ast_party_number::valid.

Referenced by dial_exec_full(), and do_forward().

00788 {
00789    struct ast_channel *chans[] = { src, dst };
00790    ast_manager_event_multichan(EVENT_FLAG_CALL, "Dial", 2, chans,
00791       "SubEvent: Begin\r\n"
00792       "Channel: %s\r\n"
00793       "Destination: %s\r\n"
00794       "CallerIDNum: %s\r\n"
00795       "CallerIDName: %s\r\n"
00796       "ConnectedLineNum: %s\r\n"
00797       "ConnectedLineName: %s\r\n"
00798       "UniqueID: %s\r\n"
00799       "DestUniqueID: %s\r\n"
00800       "Dialstring: %s\r\n",
00801       src->name, dst->name,
00802       S_COR(src->caller.id.number.valid, src->caller.id.number.str, "<unknown>"),
00803       S_COR(src->caller.id.name.valid, src->caller.id.name.str, "<unknown>"),
00804       S_COR(src->connected.id.number.valid, src->connected.id.number.str, "<unknown>"),
00805       S_COR(src->connected.id.name.valid, src->connected.id.name.str, "<unknown>"),
00806       src->uniqueid, dst->uniqueid,
00807       dialstring ? dialstring : "");
00808 }

static int setup_privacy_args ( struct privacy_args pa,
struct ast_flags64 opts,
char *  opt_args[],
struct ast_channel chan 
) [static]

returns 1 if successful, 0 or <0 if the caller should 'goto out'

Definition at line 1826 of file app_dial.c.

References ast_answer(), ast_config_AST_DATA_DIR, ast_copy_string(), ast_dsp_get_threshold_from_settings(), ast_filedelete(), ast_fileexists(), ast_log(), ast_mkdir(), ast_play_and_record(), AST_PRIVACY_ALLOW, ast_privacy_check(), AST_PRIVACY_DENY, AST_PRIVACY_KILL, AST_PRIVACY_TORTURE, AST_PRIVACY_UNKNOWN, ast_shrink_phone_number(), ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_test_flag64, ast_verb, ast_waitstream(), ast_channel::caller, ast_channel::exten, ast_party_caller::id, LOG_NOTICE, LOG_WARNING, ast_party_id::number, OPT_ARG_PRIVACY, OPT_PRIVACY, OPT_SCREEN_NOCALLERID, privacy_args::privcid, privacy_args::privdb_val, privacy_args::privintro, silencethreshold, privacy_args::status, ast_party_number::str, THRESHOLD_SILENCE, and ast_party_number::valid.

Referenced by dial_exec_full().

01828 {
01829    char callerid[60];
01830    int res;
01831    char *l;
01832    int silencethreshold;
01833 
01834    if (chan->caller.id.number.valid
01835       && !ast_strlen_zero(chan->caller.id.number.str)) {
01836       l = ast_strdupa(chan->caller.id.number.str);
01837       ast_shrink_phone_number(l);
01838       if (ast_test_flag64(opts, OPT_PRIVACY) ) {
01839          ast_verb(3, "Privacy DB is '%s', clid is '%s'\n", opt_args[OPT_ARG_PRIVACY], l);
01840          pa->privdb_val = ast_privacy_check(opt_args[OPT_ARG_PRIVACY], l);
01841       } else {
01842          ast_verb(3, "Privacy Screening, clid is '%s'\n", l);
01843          pa->privdb_val = AST_PRIVACY_UNKNOWN;
01844       }
01845    } else {
01846       char *tnam, *tn2;
01847 
01848       tnam = ast_strdupa(chan->name);
01849       /* clean the channel name so slashes don't try to end up in disk file name */
01850       for (tn2 = tnam; *tn2; tn2++) {
01851          if (*tn2 == '/')  /* any other chars to be afraid of? */
01852             *tn2 = '=';
01853       }
01854       ast_verb(3, "Privacy-- callerid is empty\n");
01855 
01856       snprintf(callerid, sizeof(callerid), "NOCALLERID_%s%s", chan->exten, tnam);
01857       l = callerid;
01858       pa->privdb_val = AST_PRIVACY_UNKNOWN;
01859    }
01860 
01861    ast_copy_string(pa->privcid, l, sizeof(pa->privcid));
01862 
01863    if (strncmp(pa->privcid, "NOCALLERID", 10) != 0 && ast_test_flag64(opts, OPT_SCREEN_NOCALLERID)) {
01864       /* if callerid is set and OPT_SCREEN_NOCALLERID is set also */
01865       ast_verb(3, "CallerID set (%s); N option set; Screening should be off\n", pa->privcid);
01866       pa->privdb_val = AST_PRIVACY_ALLOW;
01867    } else if (ast_test_flag64(opts, OPT_SCREEN_NOCALLERID) && strncmp(pa->privcid, "NOCALLERID", 10) == 0) {
01868       ast_verb(3, "CallerID blank; N option set; Screening should happen; dbval is %d\n", pa->privdb_val);
01869    }
01870    
01871    if (pa->privdb_val == AST_PRIVACY_DENY) {
01872       ast_verb(3, "Privacy DB reports PRIVACY_DENY for this callerid. Dial reports unavailable\n");
01873       ast_copy_string(pa->status, "NOANSWER", sizeof(pa->status));
01874       return 0;
01875    } else if (pa->privdb_val == AST_PRIVACY_KILL) {
01876       ast_copy_string(pa->status, "DONTCALL", sizeof(pa->status));
01877       return 0; /* Is this right? */
01878    } else if (pa->privdb_val == AST_PRIVACY_TORTURE) {
01879       ast_copy_string(pa->status, "TORTURE", sizeof(pa->status));
01880       return 0; /* is this right??? */
01881    } else if (pa->privdb_val == AST_PRIVACY_UNKNOWN) {
01882       /* Get the user's intro, store it in priv-callerintros/$CID,
01883          unless it is already there-- this should be done before the
01884          call is actually dialed  */
01885 
01886       /* make sure the priv-callerintros dir actually exists */
01887       snprintf(pa->privintro, sizeof(pa->privintro), "%s/sounds/priv-callerintros", ast_config_AST_DATA_DIR);
01888       if ((res = ast_mkdir(pa->privintro, 0755))) {
01889          ast_log(LOG_WARNING, "privacy: can't create directory priv-callerintros: %s\n", strerror(res));
01890          return -1;
01891       }
01892 
01893       snprintf(pa->privintro, sizeof(pa->privintro), "priv-callerintros/%s", pa->privcid);
01894       if (ast_fileexists(pa->privintro, NULL, NULL ) > 0 && strncmp(pa->privcid, "NOCALLERID", 10) != 0) {
01895          /* the DELUX version of this code would allow this caller the
01896             option to hear and retape their previously recorded intro.
01897          */
01898       } else {
01899          int duration; /* for feedback from play_and_wait */
01900          /* the file doesn't exist yet. Let the caller submit his
01901             vocal intro for posterity */
01902          /* priv-recordintro script:
01903 
01904             "At the tone, please say your name:"
01905 
01906          */
01907          silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
01908          ast_answer(chan);
01909          res = ast_play_and_record(chan, "priv-recordintro", pa->privintro, 4, "sln", &duration, NULL, silencethreshold, 2000, 0);  /* NOTE: I've reduced the total time to 4 sec */
01910                            /* don't think we'll need a lock removed, we took care of
01911                               conflicts by naming the pa.privintro file */
01912          if (res == -1) {
01913             /* Delete the file regardless since they hung up during recording */
01914             ast_filedelete(pa->privintro, NULL);
01915             if (ast_fileexists(pa->privintro, NULL, NULL) > 0)
01916                ast_log(LOG_NOTICE, "privacy: ast_filedelete didn't do its job on %s\n", pa->privintro);
01917             else
01918                ast_verb(3, "Successfully deleted %s intro file\n", pa->privintro);
01919             return -1;
01920          }
01921          if (!ast_streamfile(chan, "vm-dialout", chan->language) )
01922             ast_waitstream(chan, "");
01923       }
01924    }
01925    return 1; /* success */
01926 }

static int unload_module ( void   )  [static]

Definition at line 3172 of file app_dial.c.

References ast_context_destroy(), ast_context_find(), ast_context_remove_extension2(), and ast_unregister_application().

03173 {
03174    int res;
03175    struct ast_context *con;
03176 
03177    res = ast_unregister_application(app);
03178    res |= ast_unregister_application(rapp);
03179 
03180    if ((con = ast_context_find("app_dial_gosub_virtual_context"))) {
03181       ast_context_remove_extension2(con, "s", 1, NULL, 0);
03182       ast_context_destroy(con, "app_dial"); /* leave nothing behind */
03183    }
03184 
03185    return res;
03186 }

static int valid_priv_reply ( struct ast_flags64 opts,
int  res 
) [static]

Definition at line 1680 of file app_dial.c.

References ast_test_flag64, OPT_PRIVACY, and OPT_SCREENING.

01681 {
01682    if (res < '1')
01683       return 0;
01684    if (ast_test_flag64(opts, OPT_PRIVACY) && res <= '5')
01685       return 1;
01686    if (ast_test_flag64(opts, OPT_SCREENING) && res <= '4')
01687       return 1;
01688    return 0;
01689 }

static struct ast_channel* wait_for_answer ( struct ast_channel in,
struct chanlist outgoing,
int *  to,
struct ast_flags64 peerflags,
char *  opt_args[],
struct privacy_args pa,
const struct cause_args num_in,
int *  result,
char *  dtmf_progress,
const int  ignore_cc,
struct ast_party_id forced_clid,
struct ast_party_id stored_clid 
) [static, read]

Definition at line 1033 of file app_dial.c.

References ast_channel::_state, ast_cdr::answer, chanlist::aoc_s_rate_list, ast_aoc_decode(), ast_aoc_destroy_decoded(), ast_aoc_destroy_encoded(), ast_aoc_encode(), ast_aoc_get_msg_type(), AST_AOC_S, AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, AST_CAUSE_NORMAL_CLEARING, ast_cc_completed(), ast_cc_failed(), ast_cc_is_recall(), AST_CDR_ANSWERED, ast_cdr_failed(), ast_cdr_noanswer(), ast_channel_connected_line_macro(), ast_channel_early_bridge(), ast_channel_lock, ast_channel_make_compatible(), ast_channel_redirecting_macro(), ast_channel_sendhtml(), ast_channel_unlock, ast_channel_update_connected_line(), ast_check_hangup(), ast_clear_flag64, ast_connected_line_copy_from_caller(), ast_connected_line_parse_data(), AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, AST_CONTROL_ANSWER, AST_CONTROL_AOC, AST_CONTROL_BUSY, AST_CONTROL_CC, AST_CONTROL_CONGESTION, AST_CONTROL_CONNECTED_LINE, AST_CONTROL_FLASH, AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_OFFHOOK, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_REDIRECTING, AST_CONTROL_RINGING, AST_CONTROL_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, ast_copy_flags64, ast_copy_string(), ast_deactivate_generator(), ast_debug, ast_dtmf_stream(), AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_HTML, AST_FRAME_IMAGE, AST_FRAME_TEXT, AST_FRAME_VOICE, ast_frfree, ast_handle_cc_control_frame(), ast_hangup(), ast_indicate(), ast_indicate_data(), ast_log(), AST_MAX_WATCHERS, ast_party_connected_line_copy(), ast_party_connected_line_free(), ast_party_connected_line_init(), ast_party_connected_line_set(), ast_party_connected_line_set_init(), ast_poll_channel_add(), ast_poll_channel_del(), ast_read(), ast_remaining_ms(), AST_STATE_UP, ast_str_alloca, ast_string_field_set, ast_strlen_zero(), ast_test_flag64, ast_tvnow(), ast_verb, ast_waitfor_n(), ast_write(), cause_args::busy, ast_channel::caller, CAN_EARLY_BRIDGE, ast_channel::cdr, chanlist::chan, cause_args::congestion, ast_channel::connected, chanlist::connected, context, ast_frame::data, ast_frame::datalen, detect_disconnect(), DIAL_CALLERID_ABSENT, DIAL_NOFORWARDHTML, DIAL_STILLGOING, dialcontext, ast_cdr::disposition, do_forward(), ast_channel::exten, f, FEATURE_MAX_LEN, ast_frame::frametype, handle_cause(), ast_channel::hangupcause, ast_frame_subclass::integer, LOG_WARNING, chanlist::next, cause_args::nochan, onedigit_goto(), OPT_ARG_RINGBACK, OPT_CALLEE_HANGUP, OPT_CALLEE_MIXMONITOR, OPT_CALLEE_MONITOR, OPT_CALLEE_PARK, OPT_CALLEE_TRANSFER, OPT_CALLER_HANGUP, OPT_CALLER_MIXMONITOR, OPT_CALLER_MONITOR, OPT_CALLER_PARK, OPT_CALLER_TRANSFER, OPT_DTMF_EXIT, OPT_IGNORE_CONNECTEDLINE, OPT_MUSICBACK, OPT_RINGBACK, pbx_builtin_getvar_helper(), chanlist::pending_connected_update, ast_frame::ptr, privacy_args::sentringing, ast_party_connected_line::source, privacy_args::status, ast_frame::subclass, and ast_frame::uint32.

Referenced by dial_exec_full().

01040 {
01041    struct cause_args num = *num_in;
01042    int prestart = num.busy + num.congestion + num.nochan;
01043    int orig = *to;
01044    struct ast_channel *peer = NULL;
01045    /* single is set if only one destination is enabled */
01046    int single = outgoing && !outgoing->next;
01047    int caller_entertained = outgoing
01048       && ast_test_flag64(outgoing, OPT_MUSICBACK | OPT_RINGBACK);
01049 #ifdef HAVE_EPOLL
01050    struct chanlist *epollo;
01051 #endif
01052    struct ast_party_connected_line connected_caller;
01053    struct ast_str *featurecode = ast_str_alloca(FEATURE_MAX_LEN + 1);
01054    int cc_recall_core_id;
01055    int is_cc_recall;
01056    int cc_frame_received = 0;
01057    int num_ringing = 0;
01058    struct timeval start = ast_tvnow();
01059 
01060    ast_party_connected_line_init(&connected_caller);
01061    if (single) {
01062       /* Turn off hold music, etc */
01063       if (!caller_entertained) {
01064          ast_deactivate_generator(in);
01065          /* If we are calling a single channel, and not providing ringback or music, */
01066          /* then, make them compatible for in-band tone purpose */
01067          if (ast_channel_make_compatible(outgoing->chan, in) < 0) {
01068             /* If these channels can not be made compatible, 
01069              * there is no point in continuing.  The bridge
01070              * will just fail if it gets that far.
01071              */
01072             *to = -1;
01073             strcpy(pa->status, "CONGESTION");
01074             ast_cdr_failed(in->cdr);
01075             return NULL;
01076          }
01077       }
01078 
01079       if (!ast_test_flag64(outgoing, OPT_IGNORE_CONNECTEDLINE)
01080          && !ast_test_flag64(outgoing, DIAL_CALLERID_ABSENT)) {
01081          ast_channel_lock(outgoing->chan);
01082          ast_connected_line_copy_from_caller(&connected_caller, &outgoing->chan->caller);
01083          ast_channel_unlock(outgoing->chan);
01084          connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
01085          if (ast_channel_connected_line_macro(outgoing->chan, in, &connected_caller, 1, 0)) {
01086             ast_channel_update_connected_line(in, &connected_caller, NULL);
01087          }
01088          ast_party_connected_line_free(&connected_caller);
01089       }
01090    }
01091 
01092    is_cc_recall = ast_cc_is_recall(in, &cc_recall_core_id, NULL);
01093 
01094 #ifdef HAVE_EPOLL
01095    for (epollo = outgoing; epollo; epollo = epollo->next)
01096       ast_poll_channel_add(in, epollo->chan);
01097 #endif
01098 
01099    while ((*to = ast_remaining_ms(start, orig)) && !peer) {
01100       struct chanlist *o;
01101       int pos = 0; /* how many channels do we handle */
01102       int numlines = prestart;
01103       struct ast_channel *winner;
01104       struct ast_channel *watchers[AST_MAX_WATCHERS];
01105 
01106       watchers[pos++] = in;
01107       for (o = outgoing; o; o = o->next) {
01108          /* Keep track of important channels */
01109          if (ast_test_flag64(o, DIAL_STILLGOING) && o->chan)
01110             watchers[pos++] = o->chan;
01111          numlines++;
01112       }
01113       if (pos == 1) { /* only the input channel is available */
01114          if (numlines == (num.busy + num.congestion + num.nochan)) {
01115             ast_verb(2, "Everyone is busy/congested at this time (%d:%d/%d/%d)\n", numlines, num.busy, num.congestion, num.nochan);
01116             if (num.busy)
01117                strcpy(pa->status, "BUSY");
01118             else if (num.congestion)
01119                strcpy(pa->status, "CONGESTION");
01120             else if (num.nochan)
01121                strcpy(pa->status, "CHANUNAVAIL");
01122          } else {
01123             ast_verb(3, "No one is available to answer at this time (%d:%d/%d/%d)\n", numlines, num.busy, num.congestion, num.nochan);
01124          }
01125          *to = 0;
01126          if (is_cc_recall) {
01127             ast_cc_failed(cc_recall_core_id, "Everyone is busy/congested for the recall. How sad");
01128          }
01129          return NULL;
01130       }
01131       winner = ast_waitfor_n(watchers, pos, to);
01132       for (o = outgoing; o; o = o->next) {
01133          struct ast_frame *f;
01134          struct ast_channel *c = o->chan;
01135 
01136          if (c == NULL)
01137             continue;
01138          if (ast_test_flag64(o, DIAL_STILLGOING) && c->_state == AST_STATE_UP) {
01139             if (!peer) {
01140                ast_verb(3, "%s answered %s\n", c->name, in->name);
01141                if (!single && !ast_test_flag64(o, OPT_IGNORE_CONNECTEDLINE)) {
01142                   if (o->pending_connected_update) {
01143                      if (ast_channel_connected_line_macro(c, in, &o->connected, 1, 0)) {
01144                         ast_channel_update_connected_line(in, &o->connected, NULL);
01145                      }
01146                   } else if (!ast_test_flag64(o, DIAL_CALLERID_ABSENT)) {
01147                      ast_channel_lock(c);
01148                      ast_connected_line_copy_from_caller(&connected_caller, &c->caller);
01149                      ast_channel_unlock(c);
01150                      connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
01151                      if (ast_channel_connected_line_macro(c, in, &connected_caller, 1, 0)) {
01152                         ast_channel_update_connected_line(in, &connected_caller, NULL);
01153                      }
01154                      ast_party_connected_line_free(&connected_caller);
01155                   }
01156                }
01157                if (o->aoc_s_rate_list) {
01158                   size_t encoded_size;
01159                   struct ast_aoc_encoded *encoded;
01160                   if ((encoded = ast_aoc_encode(o->aoc_s_rate_list, &encoded_size, o->chan))) {
01161                      ast_indicate_data(in, AST_CONTROL_AOC, encoded, encoded_size);
01162                      ast_aoc_destroy_encoded(encoded);
01163                   }
01164                }
01165                peer = c;
01166                ast_copy_flags64(peerflags, o,
01167                   OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
01168                   OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
01169                   OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
01170                   OPT_CALLEE_PARK | OPT_CALLER_PARK |
01171                   OPT_CALLEE_MIXMONITOR | OPT_CALLER_MIXMONITOR |
01172                   DIAL_NOFORWARDHTML);
01173                ast_string_field_set(c, dialcontext, "");
01174                ast_copy_string(c->exten, "", sizeof(c->exten));
01175             }
01176             continue;
01177          }
01178          if (c != winner)
01179             continue;
01180          /* here, o->chan == c == winner */
01181          if (!ast_strlen_zero(c->call_forward)) {
01182             pa->sentringing = 0;
01183             if (!ignore_cc && (f = ast_read(c))) {
01184                if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_CC) {
01185                   /* This channel is forwarding the call, and is capable of CC, so
01186                    * be sure to add the new device interface to the list
01187                    */
01188                   ast_handle_cc_control_frame(in, c, f->data.ptr);
01189                }
01190                ast_frfree(f);
01191             }
01192 
01193             if (o->pending_connected_update) {
01194                /*
01195                 * Re-seed the chanlist's connected line information with
01196                 * previously acquired connected line info from the incoming
01197                 * channel.  The previously acquired connected line info could
01198                 * have been set through the CONNECTED_LINE dialplan function.
01199                 */
01200                o->pending_connected_update = 0;
01201                ast_channel_lock(in);
01202                ast_party_connected_line_copy(&o->connected, &in->connected);
01203                ast_channel_unlock(in);
01204             }
01205 
01206             do_forward(o, &num, peerflags, single, caller_entertained, &orig,
01207                forced_clid, stored_clid);
01208 
01209             if (single && o->chan
01210                && !ast_test_flag64(o, OPT_IGNORE_CONNECTEDLINE)
01211                && !ast_test_flag64(o, DIAL_CALLERID_ABSENT)) {
01212                ast_channel_lock(o->chan);
01213                ast_connected_line_copy_from_caller(&connected_caller, &o->chan->caller);
01214                ast_channel_unlock(o->chan);
01215                connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
01216                if (ast_channel_connected_line_macro(o->chan, in, &connected_caller, 1, 0)) {
01217                   ast_channel_update_connected_line(in, &connected_caller, NULL);
01218                }
01219                ast_party_connected_line_free(&connected_caller);
01220             }
01221             continue;
01222          }
01223          f = ast_read(winner);
01224          if (!f) {
01225             in->hangupcause = c->hangupcause;
01226 #ifdef HAVE_EPOLL
01227             ast_poll_channel_del(in, c);
01228 #endif
01229             ast_hangup(c);
01230             c = o->chan = NULL;
01231             ast_clear_flag64(o, DIAL_STILLGOING);
01232             handle_cause(in->hangupcause, &num);
01233             continue;
01234          }
01235          switch (f->frametype) {
01236          case AST_FRAME_CONTROL:
01237             switch (f->subclass.integer) {
01238             case AST_CONTROL_ANSWER:
01239                /* This is our guy if someone answered. */
01240                if (!peer) {
01241                   ast_verb(3, "%s answered %s\n", c->name, in->name);
01242                   if (!single && !ast_test_flag64(o, OPT_IGNORE_CONNECTEDLINE)) {
01243                      if (o->pending_connected_update) {
01244                         if (ast_channel_connected_line_macro(c, in, &o->connected, 1, 0)) {
01245                            ast_channel_update_connected_line(in, &o->connected, NULL);
01246                         }
01247                      } else if (!ast_test_flag64(o, DIAL_CALLERID_ABSENT)) {
01248                         ast_channel_lock(c);
01249                         ast_connected_line_copy_from_caller(&connected_caller, &c->caller);
01250                         ast_channel_unlock(c);
01251                         connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
01252                         if (ast_channel_connected_line_macro(c, in, &connected_caller, 1, 0)) {
01253                            ast_channel_update_connected_line(in, &connected_caller, NULL);
01254                         }
01255                         ast_party_connected_line_free(&connected_caller);
01256                      }
01257                   }
01258                   if (o->aoc_s_rate_list) {
01259                      size_t encoded_size;
01260                      struct ast_aoc_encoded *encoded;
01261                      if ((encoded = ast_aoc_encode(o->aoc_s_rate_list, &encoded_size, o->chan))) {
01262                         ast_indicate_data(in, AST_CONTROL_AOC, encoded, encoded_size);
01263                         ast_aoc_destroy_encoded(encoded);
01264                      }
01265                   }
01266                   peer = c;
01267                   if (peer->cdr) {
01268                      peer->cdr->answer = ast_tvnow();
01269                      peer->cdr->disposition = AST_CDR_ANSWERED;
01270                   }
01271                   ast_copy_flags64(peerflags, o,
01272                      OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
01273                      OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
01274                      OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
01275                      OPT_CALLEE_PARK | OPT_CALLER_PARK |
01276                      OPT_CALLEE_MIXMONITOR | OPT_CALLER_MIXMONITOR |
01277                      DIAL_NOFORWARDHTML);
01278                   ast_string_field_set(c, dialcontext, "");
01279                   ast_copy_string(c->exten, "", sizeof(c->exten));
01280                   if (CAN_EARLY_BRIDGE(peerflags, in, peer))
01281                      /* Setup early bridge if appropriate */
01282                      ast_channel_early_bridge(in, peer);
01283                }
01284                /* If call has been answered, then the eventual hangup is likely to be normal hangup */
01285                in->hangupcause = AST_CAUSE_NORMAL_CLEARING;
01286                c->hangupcause = AST_CAUSE_NORMAL_CLEARING;
01287                break;
01288             case AST_CONTROL_BUSY:
01289                ast_verb(3, "%s is busy\n", c->name);
01290                in->hangupcause = c->hangupcause;
01291                ast_hangup(c);
01292                c = o->chan = NULL;
01293                ast_clear_flag64(o, DIAL_STILLGOING);
01294                handle_cause(AST_CAUSE_BUSY, &num);
01295                break;
01296             case AST_CONTROL_CONGESTION:
01297                ast_verb(3, "%s is circuit-busy\n", c->name);
01298                in->hangupcause = c->hangupcause;
01299                ast_hangup(c);
01300                c = o->chan = NULL;
01301                ast_clear_flag64(o, DIAL_STILLGOING);
01302                handle_cause(AST_CAUSE_CONGESTION, &num);
01303                break;
01304             case AST_CONTROL_RINGING:
01305                /* This is a tricky area to get right when using a native
01306                 * CC agent. The reason is that we do the best we can to send only a
01307                 * single ringing notification to the caller.
01308                 *
01309                 * Call completion complicates the logic used here. CCNR is typically
01310                 * offered during a ringing message. Let's say that party A calls
01311                 * parties B, C, and D. B and C do not support CC requests, but D
01312                 * does. If we were to receive a ringing notification from B before
01313                 * the others, then we would end up sending a ringing message to
01314                 * A with no CCNR offer present.
01315                 *
01316                 * The approach that we have taken is that if we receive a ringing
01317                 * response from a party and no CCNR offer is present, we need to
01318                 * wait. Specifically, we need to wait until either a) a called party
01319                 * offers CCNR in its ringing response or b) all called parties have
01320                 * responded in some way to our call and none offers CCNR.
01321                 *
01322                 * The drawback to this is that if one of the parties has a delayed
01323                 * response or, god forbid, one just plain doesn't respond to our
01324                 * outgoing call, then this will result in a significant delay between
01325                 * when the caller places the call and hears ringback.
01326                 *
01327                 * Note also that if CC is disabled for this call, then it is perfectly
01328                 * fine for ringing frames to get sent through.
01329                 */
01330                ++num_ringing;
01331                if (ignore_cc || cc_frame_received || num_ringing == numlines) {
01332                   ast_verb(3, "%s is ringing\n", c->name);
01333                   /* Setup early media if appropriate */
01334                   if (single && !caller_entertained
01335                      && CAN_EARLY_BRIDGE(peerflags, in, c)) {
01336                      ast_channel_early_bridge(in, c);
01337                   }
01338                   if (!(pa->sentringing) && !ast_test_flag64(outgoing, OPT_MUSICBACK) && ast_strlen_zero(opt_args[OPT_ARG_RINGBACK])) {
01339                      ast_indicate(in, AST_CONTROL_RINGING);
01340                      pa->sentringing++;
01341                   }
01342                }
01343                break;
01344             case AST_CONTROL_PROGRESS:
01345                ast_verb(3, "%s is making progress passing it to %s\n", c->name, in->name);
01346                /* Setup early media if appropriate */
01347                if (single && !caller_entertained
01348                   && CAN_EARLY_BRIDGE(peerflags, in, c)) {
01349                   ast_channel_early_bridge(in, c);
01350                }
01351                if (!ast_test_flag64(outgoing, OPT_RINGBACK)) {
01352                   if (single || (!single && !pa->sentringing)) {
01353                      ast_indicate(in, AST_CONTROL_PROGRESS);
01354                   }
01355                }
01356                if (!ast_strlen_zero(dtmf_progress)) {
01357                   ast_verb(3,
01358                      "Sending DTMF '%s' to the called party as result of receiving a PROGRESS message.\n",
01359                      dtmf_progress);
01360                   ast_dtmf_stream(c, in, dtmf_progress, 250, 0);
01361                }
01362                break;
01363             case AST_CONTROL_VIDUPDATE:
01364             case AST_CONTROL_SRCUPDATE:
01365             case AST_CONTROL_SRCCHANGE:
01366                if (!single || caller_entertained) {
01367                   break;
01368                }
01369                ast_verb(3, "%s requested media update control %d, passing it to %s\n",
01370                   c->name, f->subclass.integer, in->name);
01371                ast_indicate(in, f->subclass.integer);
01372                break;
01373             case AST_CONTROL_CONNECTED_LINE:
01374                if (ast_test_flag64(o, OPT_IGNORE_CONNECTEDLINE)) {
01375                   ast_verb(3, "Connected line update to %s prevented.\n", in->name);
01376                   break;
01377                }
01378                if (!single) {
01379                   struct ast_party_connected_line connected;
01380 
01381                   ast_verb(3, "%s connected line has changed. Saving it until answer for %s\n",
01382                      c->name, in->name);
01383                   ast_party_connected_line_set_init(&connected, &o->connected);
01384                   ast_connected_line_parse_data(f->data.ptr, f->datalen, &connected);
01385                   ast_party_connected_line_set(&o->connected, &connected, NULL);
01386                   ast_party_connected_line_free(&connected);
01387                   o->pending_connected_update = 1;
01388                   break;
01389                }
01390                if (ast_channel_connected_line_macro(c, in, f, 1, 1)) {
01391                   ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
01392                }
01393                break;
01394             case AST_CONTROL_AOC:
01395                {
01396                   struct ast_aoc_decoded *decoded = ast_aoc_decode(f->data.ptr, f->datalen, o->chan);
01397                   if (decoded && (ast_aoc_get_msg_type(decoded) == AST_AOC_S)) {
01398                      ast_aoc_destroy_decoded(o->aoc_s_rate_list);
01399                      o->aoc_s_rate_list = decoded;
01400                   } else {
01401                      ast_aoc_destroy_decoded(decoded);
01402                   }
01403                }
01404                break;
01405             case AST_CONTROL_REDIRECTING:
01406                if (!single) {
01407                   /*
01408                    * Redirecting updates to the caller make sense only on single
01409                    * calls.
01410                    */
01411                   break;
01412                }
01413                if (ast_test_flag64(o, OPT_IGNORE_CONNECTEDLINE)) {
01414                   ast_verb(3, "Redirecting update to %s prevented.\n", in->name);
01415                   break;
01416                }
01417                ast_verb(3, "%s redirecting info has changed, passing it to %s\n",
01418                   c->name, in->name);
01419                if (ast_channel_redirecting_macro(c, in, f, 1, 1)) {
01420                   ast_indicate_data(in, AST_CONTROL_REDIRECTING, f->data.ptr, f->datalen);
01421                }
01422                pa->sentringing = 0;
01423                break;
01424             case AST_CONTROL_PROCEEDING:
01425                ast_verb(3, "%s is proceeding passing it to %s\n", c->name, in->name);
01426                if (single && !caller_entertained
01427                   && CAN_EARLY_BRIDGE(peerflags, in, c)) {
01428                   ast_channel_early_bridge(in, c);
01429                }
01430                if (!ast_test_flag64(outgoing, OPT_RINGBACK))
01431                   ast_indicate(in, AST_CONTROL_PROCEEDING);
01432                break;
01433             case AST_CONTROL_HOLD:
01434                /* XXX this should be saved like AST_CONTROL_CONNECTED_LINE for !single || caller_entertained */
01435                ast_verb(3, "Call on %s placed on hold\n", c->name);
01436                ast_indicate_data(in, AST_CONTROL_HOLD, f->data.ptr, f->datalen);
01437                break;
01438             case AST_CONTROL_UNHOLD:
01439                /* XXX this should be saved like AST_CONTROL_CONNECTED_LINE for !single || caller_entertained */
01440                ast_verb(3, "Call on %s left from hold\n", c->name);
01441                ast_indicate(in, AST_CONTROL_UNHOLD);
01442                break;
01443             case AST_CONTROL_OFFHOOK:
01444             case AST_CONTROL_FLASH:
01445                /* Ignore going off hook and flash */
01446                break;
01447             case AST_CONTROL_CC:
01448                if (!ignore_cc) {
01449                   ast_handle_cc_control_frame(in, c, f->data.ptr);
01450                   cc_frame_received = 1;
01451                }
01452                break;
01453             case -1:
01454                if (single && !caller_entertained) {
01455                   ast_verb(3, "%s stopped sounds\n", c->name);
01456                   ast_indicate(in, -1);
01457                   pa->sentringing = 0;
01458                }
01459                break;
01460             default:
01461                ast_debug(1, "Dunno what to do with control type %d\n", f->subclass.integer);
01462                break;
01463             }
01464             break;
01465          case AST_FRAME_VOICE:
01466          case AST_FRAME_IMAGE:
01467             if (caller_entertained) {
01468                break;
01469             }
01470             /* Fall through */
01471          case AST_FRAME_TEXT:
01472             if (single && ast_write(in, f)) {
01473                ast_log(LOG_WARNING, "Unable to write frametype: %u\n",
01474                   f->frametype);
01475             }
01476             break;
01477          case AST_FRAME_HTML:
01478             if (single && !ast_test_flag64(outgoing, DIAL_NOFORWARDHTML)
01479                && ast_channel_sendhtml(in, f->subclass.integer, f->data.ptr, f->datalen) == -1) {
01480                ast_log(LOG_WARNING, "Unable to send URL\n");
01481             }
01482             break;
01483          default:
01484             break;
01485          }
01486          ast_frfree(f);
01487       } /* end for */
01488       if (winner == in) {
01489          struct ast_frame *f = ast_read(in);
01490 #if 0
01491          if (f && (f->frametype != AST_FRAME_VOICE))
01492             printf("Frame type: %d, %d\n", f->frametype, f->subclass);
01493          else if (!f || (f->frametype != AST_FRAME_VOICE))
01494             printf("Hangup received on %s\n", in->name);
01495 #endif
01496          if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_HANGUP))) {
01497             /* Got hung up */
01498             *to = -1;
01499             strcpy(pa->status, "CANCEL");
01500             ast_cdr_noanswer(in->cdr);
01501             if (f) {
01502                if (f->data.uint32) {
01503                   in->hangupcause = f->data.uint32;
01504                }
01505                ast_frfree(f);
01506             }
01507             if (is_cc_recall) {
01508                ast_cc_completed(in, "CC completed, although the caller hung up (cancelled)");
01509             }
01510             return NULL;
01511          }
01512 
01513          /* now f is guaranteed non-NULL */
01514          if (f->frametype == AST_FRAME_DTMF) {
01515             if (ast_test_flag64(peerflags, OPT_DTMF_EXIT)) {
01516                const char *context;
01517                ast_channel_lock(in);
01518                context = pbx_builtin_getvar_helper(in, "EXITCONTEXT");
01519                if (onedigit_goto(in, context, (char) f->subclass.integer, 1)) {
01520                   ast_verb(3, "User hit %c to disconnect call.\n", f->subclass.integer);
01521                   *to = 0;
01522                   ast_cdr_noanswer(in->cdr);
01523                   *result = f->subclass.integer;
01524                   strcpy(pa->status, "CANCEL");
01525                   ast_frfree(f);
01526                   ast_channel_unlock(in);
01527                   if (is_cc_recall) {
01528                      ast_cc_completed(in, "CC completed, but the caller used DTMF to exit");
01529                   }
01530                   return NULL;
01531                }
01532                ast_channel_unlock(in);
01533             }
01534 
01535             if (ast_test_flag64(peerflags, OPT_CALLER_HANGUP) &&
01536                detect_disconnect(in, f->subclass.integer, &featurecode)) {
01537                ast_verb(3, "User requested call disconnect.\n");
01538                *to = 0;
01539                strcpy(pa->status, "CANCEL");
01540                ast_cdr_noanswer(in->cdr);
01541                ast_frfree(f);
01542                if (is_cc_recall) {
01543                   ast_cc_completed(in, "CC completed, but the caller hung up with DTMF");
01544                }
01545                return NULL;
01546             }
01547          }
01548 
01549          /* Send the frame from the in channel to all outgoing channels. */
01550          for (o = outgoing; o; o = o->next) {
01551             if (!o->chan || !ast_test_flag64(o, DIAL_STILLGOING)) {
01552                /* This outgoing channel has died so don't send the frame to it. */
01553                continue;
01554             }
01555             switch (f->frametype) {
01556             case AST_FRAME_HTML:
01557                /* Forward HTML stuff */
01558                if (!ast_test_flag64(o, DIAL_NOFORWARDHTML)
01559                   && ast_channel_sendhtml(o->chan, f->subclass.integer, f->data.ptr, f->datalen) == -1) {
01560                   ast_log(LOG_WARNING, "Unable to send URL\n");
01561                }
01562                break;
01563             case AST_FRAME_VOICE:
01564             case AST_FRAME_IMAGE:
01565                if (!single || caller_entertained) {
01566                   /*
01567                    * We are calling multiple parties or caller is being
01568                    * entertained and has thus not been made compatible.
01569                    * No need to check any other called parties.
01570                    */
01571                   goto skip_frame;
01572                }
01573                /* Fall through */
01574             case AST_FRAME_TEXT:
01575             case AST_FRAME_DTMF_BEGIN:
01576             case AST_FRAME_DTMF_END:
01577                if (ast_write(o->chan, f)) {
01578                   ast_log(LOG_WARNING, "Unable to forward frametype: %u\n",
01579                      f->frametype);
01580                }
01581                break;
01582             case AST_FRAME_CONTROL:
01583                switch (f->subclass.integer) {
01584                case AST_CONTROL_HOLD:
01585                   ast_verb(3, "Call on %s placed on hold\n", o->chan->name);
01586                   ast_indicate_data(o->chan, AST_CONTROL_HOLD, f->data.ptr, f->datalen);
01587                   break;
01588                case AST_CONTROL_UNHOLD:
01589                   ast_verb(3, "Call on %s left from hold\n", o->chan->name);
01590                   ast_indicate(o->chan, AST_CONTROL_UNHOLD);
01591                   break;
01592                case AST_CONTROL_VIDUPDATE:
01593                case AST_CONTROL_SRCUPDATE:
01594                case AST_CONTROL_SRCCHANGE:
01595                   if (!single || caller_entertained) {
01596                      /*
01597                       * We are calling multiple parties or caller is being
01598                       * entertained and has thus not been made compatible.
01599                       * No need to check any other called parties.
01600                       */
01601                      goto skip_frame;
01602                   }
01603                   ast_verb(3, "%s requested media update control %d, passing it to %s\n",
01604                      in->name, f->subclass.integer, o->chan->name);
01605                   ast_indicate(o->chan, f->subclass.integer);
01606                   break;
01607                case AST_CONTROL_CONNECTED_LINE:
01608                   if (ast_channel_connected_line_macro(in, o->chan, f, 0, 1)) {
01609                      ast_indicate_data(o->chan, f->subclass.integer, f->data.ptr, f->datalen);
01610                   }
01611                   break;
01612                case AST_CONTROL_REDIRECTING:
01613                   if (ast_channel_redirecting_macro(in, o->chan, f, 0, 1)) {
01614                      ast_indicate_data(o->chan, f->subclass.integer, f->data.ptr, f->datalen);
01615                   }
01616                   break;
01617                default:
01618                   /* We are not going to do anything with this frame. */
01619                   goto skip_frame;
01620                }
01621                break;
01622             default:
01623                /* We are not going to do anything with this frame. */
01624                goto skip_frame;
01625             }
01626          }
01627 skip_frame:;
01628          ast_frfree(f);
01629       }
01630    }
01631 
01632    if (!*to) {
01633       ast_verb(3, "Nobody picked up in %d ms\n", orig);
01634    }
01635    if (!*to || ast_check_hangup(in)) {
01636       ast_cdr_noanswer(in->cdr);
01637    }
01638 
01639 #ifdef HAVE_EPOLL
01640    for (epollo = outgoing; epollo; epollo = epollo->next) {
01641       if (epollo->chan)
01642          ast_poll_channel_del(in, epollo->chan);
01643    }
01644 #endif
01645 
01646    if (is_cc_recall) {
01647       ast_cc_completed(in, "Recall completed!");
01648    }
01649    return peer;
01650 }


Variable Documentation

const char app[] = "Dial" [static]

Definition at line 542 of file app_dial.c.

const char rapp[] = "RetryDial" [static]

Definition at line 543 of file app_dial.c.


Generated on 7 Aug 2019 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1