@ -480,7 +480,7 @@ struct parkeduser {
enum ast_control_frame_type hold_method ;
unsigned int notquiteyet : 1 ;
unsigned int options_specified : 1 ;
char peername [ 1024 ] ;
char peername [ AST_CHANNEL_NAME ] ;
unsigned char moh_trys ;
/*! Parking lot this entry belongs to. Holds a parking lot reference. */
struct ast_parkinglot * parkinglot ;
@ -1169,6 +1169,32 @@ static struct ast_parkinglot *create_dynamic_parkinglot(const char *name, struct
return parkinglot ;
}
/*!
* \ internal
* \ brief Abort parking a call that has not completed parking yet .
*
* \ param pu Parked user item to clean up .
*
* \ note The parking lot parkings list is locked on entry .
*
* \ return Nothing
*/
static void park_space_abort ( struct parkeduser * pu )
{
struct ast_parkinglot * parkinglot ;
parkinglot = pu - > parkinglot ;
/* Put back the parking space just allocated. */
- - parkinglot - > next_parking_space ;
AST_LIST_REMOVE ( & parkinglot - > parkings , pu , list ) ;
AST_LIST_UNLOCK ( & parkinglot - > parkings ) ;
parkinglot_unref ( parkinglot ) ;
ast_free ( pu ) ;
}
/*!
* \ internal
* \ brief Reserve a parking space in a parking lot for a call being parked .
@ -1525,38 +1551,80 @@ static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, st
return 0 ;
}
/*! \brief Park a call */
int ast_park_call ( struct ast_channel * chan , struct ast_channel * peer , int timeout , const char * parkexten , int * extout )
int ast_park_call_exten ( struct ast_channel * park_me , struct ast_channel * parker , const char * park_exten , const char * park_context , int timeout , int * extout )
{
int res ;
char * parse ;
const char * app_data ;
struct ast_exten * exten ;
struct park_app_args app_args ;
struct ast_park_call_args args = {
. timeout = timeout ,
. extout = extout ,
} ;
if ( ! park_exten | | ! park_context ) {
return park_call_full ( park_me , parker , & args ) ;
}
/*
* Determiine if the specified park extension has an exclusive
* parking lot to use .
*/
if ( parker & & parker ! = park_me ) {
ast_autoservice_start ( park_me ) ;
}
exten = get_parking_exten ( park_exten , parker , park_context ) ;
if ( exten ) {
app_data = ast_get_extension_app_data ( exten ) ;
if ( ! app_data ) {
app_data = " " ;
}
parse = ast_strdupa ( app_data ) ;
AST_STANDARD_APP_ARGS ( app_args , parse ) ;
if ( ! ast_strlen_zero ( app_args . pl_name ) ) {
/* Find the specified exclusive parking lot */
args . parkinglot = find_parkinglot ( app_args . pl_name ) ;
if ( ! args . parkinglot & & parkeddynamic ) {
args . parkinglot = create_dynamic_parkinglot ( app_args . pl_name , park_me ) ;
}
}
}
if ( parker & & parker ! = park_me ) {
ast_autoservice_stop ( park_me ) ;
}
res = park_call_full ( park_me , parker , & args ) ;
if ( args . parkinglot ) {
parkinglot_unref ( args . parkinglot ) ;
}
return res ;
}
int ast_park_call ( struct ast_channel * park_me , struct ast_channel * parker , int timeout , const char * park_exten , int * extout )
{
struct ast_park_call_args args = {
. timeout = timeout ,
. extout = extout ,
} ;
return park_call_full ( chan , peer , & args ) ;
return park_call_full ( park_me, park er, & args ) ;
}
/*!
* \ brief Park call via masqueraded channel and announce parking spot on peer channel .
*
* \ param rchan the real channel to be parked
* \ param peer the channel to have the parking read to .
* \ param timeout is a timeout in milliseconds
* \ param extout is a parameter to an int that will hold the parked location , or NULL if you want .
* \ param play_announcement TRUE if to play which parking space call parked in to peer .
* \ param args Optional additional parking options when parking a call .
* \ param args Additional parking options when parking a call .
*
* \ retval 0 on success .
* \ retval - 1 on failure .
*/
static int masq_park_call ( struct ast_channel * rchan , struct ast_channel * peer , int timeout , int * extout , int play_announcement , struct ast_park_call_args * args )
static int masq_park_call ( struct ast_channel * rchan , struct ast_channel * peer , struct ast_park_call_args * args )
{
struct ast_channel * chan ;
struct ast_park_call_args park_args = { 0 , } ;
if ( ! args ) {
args = & park_args ;
args - > timeout = timeout ;
args - > extout = extout ;
}
/* Make a new, channel that we'll use to masquerade in the real one */
chan = ast_channel_alloc ( 0 , AST_STATE_DOWN , 0 , 0 , rchan - > accountcode , rchan - > exten ,
@ -1577,7 +1645,6 @@ static int masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, i
args - > pu = park_space_reserve ( rchan , peer , args ) ;
if ( ! args - > pu ) {
chan - > hangupcause = AST_CAUSE_SWITCH_CONGESTION ;
ast_hangup ( chan ) ;
if ( ! ast_test_flag ( args , AST_PARK_OPT_SILENCE ) ) {
if ( peer = = rchan ) {
@ -1594,7 +1661,22 @@ static int masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, i
/* Make formats okay */
chan - > readformat = rchan - > readformat ;
chan - > writeformat = rchan - > writeformat ;
ast_channel_masquerade ( chan , rchan ) ;
if ( ast_channel_masquerade ( chan , rchan ) ) {
park_space_abort ( args - > pu ) ;
args - > pu = NULL ;
ast_hangup ( chan ) ;
if ( ! ast_test_flag ( args , AST_PARK_OPT_SILENCE ) ) {
if ( peer = = rchan ) {
/* Only have one channel to worry about. */
ast_stream_and_wait ( peer , " pbx-parkingfailed " , " " ) ;
} else if ( peer ) {
/* Have two different channels to worry about. */
play_message_on_chan ( peer , rchan , " failure message " , " pbx-parkingfailed " ) ;
}
}
return - 1 ;
}
/* Setup the extensions and such */
set_c_e_p ( chan , rchan - > context , rchan - > exten , rchan - > priority ) ;
@ -1611,34 +1693,77 @@ static int masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, i
peer = chan ;
}
if ( peer & & ( ! play_announcement & & args = = & park_args ) ) {
args - > orig_chan_name = ast_strdupa ( peer - > name ) ;
}
/* parking space reserved, return code check unnecessary */
park_call_full ( chan , peer , args ) ;
return 0 ;
}
int ast_masq_park_call ( struct ast_channel * rchan , struct ast_channel * p eer, int timeout , int * extout )
int ast_masq_park_call _exten ( struct ast_channel * park_me , struct ast_channel * p ark er, const char * park_ exten, const cha r * park_context , int timeout , int * extout )
{
return masq_park_call ( rchan , peer , timeout , extout , 0 , NULL ) ;
int res ;
char * parse ;
const char * app_data ;
struct ast_exten * exten ;
struct park_app_args app_args ;
struct ast_park_call_args args = {
. timeout = timeout ,
. extout = extout ,
} ;
if ( parker ) {
args . orig_chan_name = ast_strdupa ( parker - > name ) ;
}
if ( ! park_exten | | ! park_context ) {
return masq_park_call ( park_me , parker , & args ) ;
}
/*
* Determiine if the specified park extension has an exclusive
* parking lot to use .
*/
if ( parker & & parker ! = park_me ) {
ast_autoservice_start ( park_me ) ;
}
exten = get_parking_exten ( park_exten , parker , park_context ) ;
if ( exten ) {
app_data = ast_get_extension_app_data ( exten ) ;
if ( ! app_data ) {
app_data = " " ;
}
parse = ast_strdupa ( app_data ) ;
AST_STANDARD_APP_ARGS ( app_args , parse ) ;
if ( ! ast_strlen_zero ( app_args . pl_name ) ) {
/* Find the specified exclusive parking lot */
args . parkinglot = find_parkinglot ( app_args . pl_name ) ;
if ( ! args . parkinglot & & parkeddynamic ) {
args . parkinglot = create_dynamic_parkinglot ( app_args . pl_name , park_me ) ;
}
}
}
if ( parker & & parker ! = park_me ) {
ast_autoservice_stop ( park_me ) ;
}
res = masq_park_call ( park_me , parker , & args ) ;
if ( args . parkinglot ) {
parkinglot_unref ( args . parkinglot ) ;
}
return res ;
}
/*!
* \ brief Park call via masqueraded channel and announce parking spot on peer channel .
*
* \ param rchan the real channel to be parked
* \ param peer the channel to have the parking read to .
* \ param args Optional additional parking options when parking a call .
*
* \ retval 0 on success .
* \ retval - 1 on failure .
*/
static int masq_park_call_announce ( struct ast_channel * rchan , struct ast_channel * peer , struct ast_park_call_args * args )
int ast_masq_park_call ( struct ast_channel * rchan , struct ast_channel * peer , int timeout , int * extout )
{
return masq_park_call ( rchan , peer , 0 , NULL , 1 , args ) ;
struct ast_park_call_args args = {
. timeout = timeout ,
. extout = extout ,
} ;
if ( peer ) {
args . orig_chan_name = ast_strdupa ( peer - > name ) ;
}
return masq_park_call ( rchan , peer , & args ) ;
}
static int finishup ( struct ast_channel * chan )
@ -1702,7 +1827,7 @@ static int xfer_park_call_helper(struct ast_channel *park_me, struct ast_channel
parkinglot_unref ( args . parkinglot ) ;
return - 1 ;
}
res = masq_park_call _announce ( park_me , parker , & args ) ;
res = masq_park_call ( park_me , parker , & args ) ;
parkinglot_unref ( args . parkinglot ) ;
} else {
/* Parking failed because parking lot does not exist. */
@ -1751,6 +1876,7 @@ static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer,
{
struct ast_channel * parker ;
struct ast_channel * parkee ;
struct ast_park_call_args args = { 0 , } ;
/*
* We used to set chan ' s exten and priority to " s " and 1 here ,
@ -1779,8 +1905,7 @@ static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer,
/* one direction used to call park_call.... */
set_peers ( & parker , & parkee , peer , chan , sense ) ;
return masq_park_call_announce ( parkee , parker , NULL )
? AST_FEATURE_RETURN_SUCCESS : - 1 ;
return masq_park_call ( parkee , parker , & args ) ? AST_FEATURE_RETURN_SUCCESS : - 1 ;
}
/*!
@ -4826,7 +4951,7 @@ static int park_call_exec(struct ast_channel *chan, const char *data)
}
}
if ( args . parkinglot ) {
res = masq_park_call _announce ( chan , chan , & args ) ;
res = masq_park_call ( chan , chan , & args ) ;
parkinglot_unref ( args . parkinglot ) ;
} else {
/* Parking failed because the parking lot does not exist. */
@ -6965,7 +7090,7 @@ static int manager_park(struct mansession *s, const struct message *m)
args . parkinglot = find_parkinglot ( parkinglotname ) ;
}
res = masq_park_call ( ch1 , ch2 , 0 , NULL , 0 , & args ) ;
res = masq_park_call ( ch1 , ch2 , & args ) ;
if ( ! res ) {
ast_softhangup ( ch2 , AST_SOFTHANGUP_EXPLICIT ) ;
astman_send_ack ( s , m , " Park successful " ) ;
@ -7888,7 +8013,7 @@ AST_TEST_DEFINE(features_test)
pbx_builtin_setvar_helper ( test_channel1 , " PARKINGDYNCONTEXT " , unique_context_2 ) ;
pbx_builtin_setvar_helper ( test_channel1 , " PARKINGDYNEXTEN " , parkinglot_parkext ) ;
pbx_builtin_setvar_helper ( test_channel1 , " PARKINGDYNPOS " , parkinglot_range ) ;
if ( masq_park_call ( test_channel1 , NULL , 0 , NULL , 0 , & args ) ) {
if ( masq_park_call ( test_channel1 , NULL , & args ) ) {
res = - 1 ;
goto exit_features_test ;
}