@ -259,21 +259,26 @@ static int adsi_announce_park(struct ast_channel *chan, int parkingnum)
return adsi_print ( chan , message , justify , 1 ) ;
}
/*--- ast_park_call: Park a call */
/* We put the user in the parking list, then wake up the parking thread to be sure it looks
after these channels too */
int ast_park_call ( struct ast_channel * chan , struct ast_channel * peer , int timeout , int * extout )
{
/* We put the user in the parking list, then wake up the parking thread to be sure it looks
after these channels too */
struct parkeduser * pu , * cur ;
int i , x , parking_range ;
char exten [ AST_MAX_EXTENSION ] ;
struct ast_context * con ;
pu = malloc ( sizeof ( struct parkeduser ) ) ;
if ( pu ) {
memset ( pu , 0 , sizeof ( struct parkeduser ) ) ;
if ( ! pu ) {
ast_log ( LOG_WARNING , " Out of memory \n " ) ;
return - 1 ;
}
memset ( pu , 0 , sizeof ( struct parkeduser ) ) ;
ast_mutex_lock ( & parking_lock ) ;
parking_range = parking_stop - parking_start + 1 ;
for ( i = 0 ; i < parking_range ; i + + ) {
x = ( i + parking_offset ) % parking_range + parking_start ;
parking_range = parking_stop - parking_start + 1 ;
for ( i = 0 ; i < parking_range ; i + + ) {
x = ( i + parking_offset ) % parking_range + parking_start ;
cur = parkinglot ;
while ( cur ) {
if ( cur - > parkingnum = = x )
@ -284,8 +289,14 @@ int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeou
break ;
}
if ( i < parking_range ) {
if ( parkfindnext ) parking_offset = x - parking_start + 1 ;
if ( ! ( i < parking_range ) ) {
ast_log ( LOG_WARNING , " No more parking spaces \n " ) ;
free ( pu ) ;
ast_mutex_unlock ( & parking_lock ) ;
return - 1 ;
}
if ( parkfindnext )
parking_offset = x - parking_start + 1 ;
chan - > appl = " Parked Call " ;
chan - > data = NULL ;
@ -303,9 +314,9 @@ int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeou
pu - > parkingtime = parkingtime ;
if ( extout )
* extout = x ;
if ( peer ) {
ast_copy_string ( pu - > peername , peer - > name , sizeof ( pu - > peername ) ) ;
}
if ( peer )
ast_copy_string ( pu - > peername , peer - > name , sizeof ( pu - > peername ) ) ;
/* Remember what had been dialed, so that if the parking
expires , we try to come back to the same place */
if ( ! ast_strlen_zero ( chan - > macrocontext ) )
@ -329,7 +340,7 @@ int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeou
/* Wake up the (presumably select()ing) thread */
pthread_kill ( parking_thread , SIGURG ) ;
if ( option_verbose > 1 )
ast_verbose ( VERBOSE_PREFIX_2 " Parked %s on %d. Will timeout back to %s,%s, %d in %d seconds\n " , pu - > chan - > name , pu - > parkingnum , pu - > context , pu - > exten , pu - > priority , ( pu - > parkingtime / 1000 ) ) ;
ast_verbose ( VERBOSE_PREFIX_2 " Parked %s on %d. Will timeout back to extension [%s] %s, %d in %d seconds\n " , pu - > chan - > name , pu - > parkingnum , pu - > context , pu - > exten , pu - > priority , ( pu - > parkingtime / 1000 ) ) ;
manager_event ( EVENT_FLAG_CALL , " ParkedCall " ,
" Exten: %d \r \n "
@ -354,7 +365,7 @@ int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeou
}
con = ast_context_find ( parking_con ) ;
if ( ! con ) {
con = ast_context_create ( NULL , parking_con , registrar ) ;
con = ast_context_create ( NULL , parking_con , registrar ) ;
if ( ! con ) {
ast_log ( LOG_ERROR , " Parking context '%s' does not exist and unable to create \n " , parking_con ) ;
}
@ -363,7 +374,8 @@ int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeou
snprintf ( exten , sizeof ( exten ) , " %d " , x ) ;
ast_add_extension2 ( con , 1 , exten , 1 , NULL , NULL , parkedcall , strdup ( exten ) , FREE , registrar ) ;
}
if ( peer ) ast_say_digits ( peer , pu - > parkingnum , " " , peer - > language ) ;
if ( peer )
ast_say_digits ( peer , pu - > parkingnum , " " , peer - > language ) ;
if ( pu - > notquiteyet ) {
/* Wake up parking thread if we're really done */
ast_moh_start ( pu - > chan , NULL ) ;
@ -371,36 +383,29 @@ int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeou
pthread_kill ( parking_thread , SIGURG ) ;
}
return 0 ;
} else {
ast_log ( LOG_WARNING , " No more parking spaces \n " ) ;
free ( pu ) ;
ast_mutex_unlock ( & parking_lock ) ;
return - 1 ;
}
} else {
ast_log ( LOG_WARNING , " Out of memory \n " ) ;
return - 1 ;
}
return 0 ;
}
int ast_masq_park_call ( struct ast_channel * rchan , struct ast_channel * peer , int timeout , int * extout )
{
struct ast_channel * chan ;
struct ast_frame * f ;
/* Make a new, fake channel that we'll use to masquerade in the real one */
chan = ast_channel_alloc ( 0 ) ;
if ( chan ) {
/* Let us keep track of the channel name */
snprintf ( chan - > name , sizeof ( chan - > name ) , " Parked/%s " , rchan - > name ) ;
/* Make formats okay */
chan - > readformat = rchan - > readformat ;
chan - > writeformat = rchan - > writeformat ;
ast_channel_masquerade ( chan , rchan ) ;
/* Setup the extensions and such */
ast_copy_string ( chan - > context , rchan - > context , sizeof ( chan - > context ) ) ;
ast_copy_string ( chan - > exten , rchan - > exten , sizeof ( chan - > exten ) ) ;
chan - > priority = rchan - > priority ;
/* Make the masq execute */
f = ast_read ( chan ) ;
if ( f )
@ -534,8 +539,8 @@ static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *p
transferer = chan ;
transferee = peer ;
}
if ( ! ( transferer_real_context = pbx_builtin_getvar_helper ( transferee , " TRANSFER_CONTEXT " ) ) & &
! ( transferer_real_context = pbx_builtin_getvar_helper ( transferer , " TRANSFER_CONTEXT " ) ) ) {
if ( ! ( transferer_real_context = pbx_builtin_getvar_helper ( transferee , " TRANSFER_CONTEXT " ) ) & &
! ( transferer_real_context = pbx_builtin_getvar_helper ( transferer , " TRANSFER_CONTEXT " ) ) ) {
/* Use the non-macro context to transfer the call */
if ( ! ast_strlen_zero ( transferer - > macrocontext ) )
transferer_real_context = transferer - > macrocontext ;
@ -587,10 +592,10 @@ static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *p
the thread dies - - We have to be careful now though . We are responsible for
hanging up the channel , else it will never be hung up ! */
if ( transferer = = peer )
res = AST_PBX_KEEPALIVE ;
if ( transferer = = peer )
res = AST_PBX_KEEPALIVE ;
else
res = AST_PBX_NO_HANGUP_PEER ;
res = AST_PBX_NO_HANGUP_PEER ;
return res ;
} else {
ast_log ( LOG_WARNING , " Unable to park call %s \n " , transferee - > name ) ;
@ -683,7 +688,7 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
ast_moh_start ( transferee , NULL ) ;
memset ( xferto , 0 , sizeof ( xferto ) ) ;
/* Transfer */
if ( ( res = ast_streamfile ( transferer , " pbx-transfer " , transferer - > language ) ) ) {
if ( ( res = ast_streamfile ( transferer , " pbx-transfer " , transferer - > language ) ) ) {
ast_moh_stop ( transferee ) ;
ast_autoservice_stop ( transferee ) ;
ast_indicate ( transferee , AST_CONTROL_UNHOLD ) ;
@ -705,7 +710,7 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
snprintf ( dialstr , sizeof ( dialstr ) , " %s@%s/n " , xferto , transferer_real_context ) ;
newchan = ast_feature_request_and_dial ( transferer , " Local " , ast_best_codec ( transferer - > nativeformats ) , dialstr , 15000 , & outstate , cid_num , cid_name ) ;
ast_indicate ( transferer , - 1 ) ;
if ( newchan ) {
if ( newchan ) {
res = ast_channel_make_compatible ( transferer , newchan ) ;
if ( res < 0 ) {
ast_log ( LOG_WARNING , " Had to drop call because I couldn't make %s compatible with %s \n " , transferer - > name , newchan - > name ) ;
@ -745,8 +750,8 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
ast_moh_stop ( transferee ) ;
if ( ( ast_autoservice_stop ( transferee ) < 0 )
| | ( ast_waitfordigit ( transferee , 100 ) < 0 )
| | ( ast_waitfordigit ( newchan , 100 ) < 0 )
| | ( ast_waitfordigit ( transferee , 100 ) < 0 )
| | ( ast_waitfordigit ( newchan , 100 ) < 0 )
| | ast_check_hangup ( transferee )
| | ast_check_hangup ( newchan ) ) {
ast_hangup ( newchan ) ;
@ -859,7 +864,7 @@ struct ast_call_feature builtin_features[] =
static void unmap_features ( void )
{
int x ;
for ( x = 0 ; x < FEATURES_COUNT ; x + + )
for ( x = 0 ; x < FEATURES_COUNT ; x + + )
strcpy ( builtin_features [ x ] . exten , builtin_features [ x ] . default_exten ) ;
}
@ -867,7 +872,7 @@ static int remap_feature(const char *name, const char *value)
{
int x ;
int res = - 1 ;
for ( x = 0 ; x < FEATURES_COUNT ; x + + ) {
for ( x = 0 ; x < FEATURES_COUNT ; x + + ) {
if ( ! strcasecmp ( name , builtin_features [ x ] . sname ) ) {
ast_copy_string ( builtin_features [ x ] . exten , value , sizeof ( builtin_features [ x ] . exten ) ) ;
if ( option_verbose > 1 )
@ -944,7 +949,7 @@ static struct ast_channel *ast_feature_request_and_dial(struct ast_channel *call
ast_indicate ( caller , AST_CONTROL_RINGING ) ;
/* support dialing of the featuremap disconnect code while performing an attended tranfer */
for ( x = 0 ; x < FEATURES_COUNT ; x + + ) {
for ( x = 0 ; x < FEATURES_COUNT ; x + + ) {
if ( strcasecmp ( builtin_features [ x ] . sname , " disconnect " ) )
continue ;
@ -1106,9 +1111,9 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
int hasfeatures = 0 ;
int hadfeatures = 0 ;
struct ast_option_header * aoh ;
struct timeval start ;
struct timeval start = { 0 , 0 } ;
struct ast_bridge_config backup_config ;
int allowdisconnect_in , allowdisconnect_out , allowredirect_in , allowredirect_out ;
int allowdisconnect_in , allowdisconnect_out , allowredirect_in , allowredirect_out ;
char * monitor_exec ;
memset ( & backup_config , 0 , sizeof ( backup_config ) ) ;
@ -1142,11 +1147,12 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
return - 1 ;
peer - > appl = " Bridged Call " ;
peer - > data = chan - > name ;
/* copy the userfield from the B-leg to A-leg if applicable */
if ( chan - > cdr & & peer - > cdr & & ! ast_strlen_zero ( peer - > cdr - > userfield ) ) {
char tmp [ 256 ] ;
if ( ! ast_strlen_zero ( chan - > cdr - > userfield ) ) {
snprintf ( tmp , sizeof ( tmp ) , " %s;%s " , chan - > cdr - > userfield , peer - > cdr - > userfield ) ;
snprintf ( tmp , sizeof ( tmp ) , " %s;%s " , chan - > cdr - > userfield , peer - > cdr - > userfield ) ;
ast_cdr_appenduserfield ( chan , tmp ) ;
} else
ast_cdr_setuserfield ( chan , peer - > cdr - > userfield ) ;
@ -1157,7 +1163,7 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
for ( ; ; ) {
if ( config - > timelimit )
start = ast_tvnow ( ) ;
res = ast_channel_bridge ( chan , peer , config , & f , & who ) ;
res = ast_channel_bridge ( chan , peer , config , & f , & who ) ;
if ( config - > timelimit ) {
/* Update time limit for next pass */
diff = ast_tvdiff_ms ( ast_tvnow ( ) , start ) ;
@ -1253,6 +1259,7 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
char * featurecode ;
int sense ;
struct ast_channel * other ;
hadfeatures = hasfeatures ;
/* This cannot overrun because the longest feature is one shorter than our buffer */
if ( who = = chan ) {
@ -1293,7 +1300,7 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
/* Setup temporary config options */
config - > play_warning = 0 ;
ast_clear_flag ( & ( config - > features_caller ) , AST_FEATURE_PLAY_WARNING ) ;
ast_clear_flag ( & ( config - > features_callee ) , AST_FEATURE_PLAY_WARNING ) ;
ast_clear_flag ( & ( config - > features_callee ) , AST_FEATURE_PLAY_WARNING ) ;
config - > warning_freq = 0 ;
config - > warning_sound = NULL ;
config - > end_sound = NULL ;
@ -1408,7 +1415,7 @@ static void *do_parking_thread(void *ignore)
ast_log ( LOG_WARNING , " Whoa, no parking context? \n " ) ;
free ( pt ) ;
} else {
for ( x = 0 ; x < AST_MAX_FDS ; x + + ) {
for ( x = 0 ; x < AST_MAX_FDS ; x + + ) {
if ( ( pu - > chan - > fds [ x ] > - 1 ) & & ( FD_ISSET ( pu - > chan - > fds [ x ] , & rfds ) | | FD_ISSET ( pu - > chan - > fds [ x ] , & efds ) ) ) {
if ( FD_ISSET ( pu - > chan - > fds [ x ] , & efds ) )
ast_set_flag ( pu - > chan , AST_FLAG_EXCEPTION ) ;
@ -1598,14 +1605,14 @@ static int park_exec(struct ast_channel *chan, void *data)
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Channel %s connected to parked call %d \n " , chan - > name , park ) ;
memset ( & config , 0 , sizeof ( struct ast_bridge_config ) ) ;
memset ( & config , 0 , sizeof ( struct ast_bridge_config ) ) ;
ast_set_flag ( & ( config . features_callee ) , AST_FEATURE_REDIRECT ) ;
ast_set_flag ( & ( config . features_caller ) , AST_FEATURE_REDIRECT ) ;
config . timelimit = 0 ;
config . play_warning = 0 ;
config . warning_freq = 0 ;
config . warning_sound = NULL ;
res = ast_bridge_call ( chan , peer , & config ) ;
res = ast_bridge_call ( chan , peer , & config ) ;
/* Simulate the PBX hanging up */
if ( res ! = AST_PBX_NO_HANGUP_PEER )
@ -1688,6 +1695,7 @@ static char showparked_help[] =
static struct ast_cli_entry showparked =
{ { " show " , " parkedcalls " , NULL } , handle_parkedcalls , " Lists parked calls " , showparked_help } ;
/* Dump lot status */
static int manager_parking_status ( struct mansession * s , struct message * m )
{
@ -1734,6 +1742,41 @@ static int manager_parking_status( struct mansession *s, struct message *m )
}
int ast_pickup_call ( struct ast_channel * chan )
{
struct ast_channel * cur = NULL ;
int res = - 1 ;
while ( ( cur = ast_channel_walk_locked ( cur ) ) ! = NULL ) {
if ( ! cur - > pbx & &
( cur ! = chan ) & &
( chan - > pickupgroup & cur - > callgroup ) & &
( ( cur - > _state = = AST_STATE_RINGING ) | |
( cur - > _state = = AST_STATE_RING ) ) ) {
break ;
}
ast_mutex_unlock ( & cur - > lock ) ;
}
if ( cur ) {
if ( option_debug )
ast_log ( LOG_DEBUG , " Call pickup on chan '%s' by '%s' \n " , cur - > name , chan - > name ) ;
res = ast_answer ( chan ) ;
if ( res )
ast_log ( LOG_WARNING , " Unable to answer '%s' \n " , chan - > name ) ;
res = ast_queue_control ( chan , AST_CONTROL_ANSWER ) ;
if ( res )
ast_log ( LOG_WARNING , " Unable to queue answer on '%s' \n " , chan - > name ) ;
res = ast_channel_masquerade ( cur , chan ) ;
if ( res )
ast_log ( LOG_WARNING , " Unable to masquerade '%s' into '%s' \n " , chan - > name , cur - > name ) ; /* Done */
ast_mutex_unlock ( & cur - > lock ) ;
} else {
if ( option_debug )
ast_log ( LOG_DEBUG , " No call pickup possible... \n " ) ;
}
return res ;
}
static int load_config ( void )
{
int start = 0 , end = 0 ;
@ -1834,50 +1877,17 @@ int load_module(void)
if ( ! res )
res = ast_register_application ( parkcall , park_call_exec , synopsis2 , descrip2 ) ;
if ( ! res ) {
ast_manager_register ( " ParkedCalls " , 0 , manager_parking_status , " List parked calls " ) ;
ast_manager_register ( " ParkedCalls " , 0 , manager_parking_status , " List parked calls " ) ;
}
return res ;
}
int ast_pickup_call ( struct ast_channel * chan )
{
struct ast_channel * cur = NULL ;
int res = - 1 ;
while ( ( cur = ast_channel_walk_locked ( cur ) ) ! = NULL ) {
if ( ! cur - > pbx & &
( cur ! = chan ) & &
( chan - > pickupgroup & cur - > callgroup ) & &
( ( cur - > _state = = AST_STATE_RINGING ) | |
( cur - > _state = = AST_STATE_RING ) ) ) {
break ;
}
ast_mutex_unlock ( & cur - > lock ) ;
}
if ( cur ) {
if ( option_debug )
ast_log ( LOG_DEBUG , " Call pickup on chan '%s' by '%s' \n " , cur - > name , chan - > name ) ;
res = ast_answer ( chan ) ;
if ( res )
ast_log ( LOG_WARNING , " Unable to answer '%s' \n " , chan - > name ) ;
res = ast_queue_control ( chan , AST_CONTROL_ANSWER ) ;
if ( res )
ast_log ( LOG_WARNING , " Unable to queue answer on '%s' \n " , chan - > name ) ;
res = ast_channel_masquerade ( cur , chan ) ;
if ( res )
ast_log ( LOG_WARNING , " Unable to masquerade '%s' into '%s' \n " , chan - > name , cur - > name ) ; /* Done */
ast_mutex_unlock ( & cur - > lock ) ;
} else {
if ( option_debug )
ast_log ( LOG_DEBUG , " No call pickup possible... \n " ) ;
}
return res ;
}
int unload_module ( void )
{
STANDARD_HANGUP_LOCALUSERS ;
ast_manager_unregister ( " ParkedCalls " ) ;
ast_manager_unregister ( " ParkedCalls " ) ;
ast_cli_unregister ( & showfeatures ) ;
ast_cli_unregister ( & showparked ) ;
ast_unregister_application ( parkcall ) ;
@ -1886,7 +1896,7 @@ int unload_module(void)
char * description ( void )
{
return " Call Parking Resource" ;
return " Call Features Resource" ;
}
int usecount ( void )