@ -3481,6 +3481,28 @@ static int iax2_hangup(struct ast_channel *c)
return 0 ;
}
/*!
* \ note expects the pvt to be locked
*/
static int wait_for_peercallno ( struct chan_iax2_pvt * pvt )
{
unsigned short callno = pvt - > callno ;
if ( ! pvt - > peercallno ) {
/* We don't know the remote side's call number, yet. :( */
int count = 10 ;
while ( count - - & & pvt & & ! pvt - > peercallno ) {
DEADLOCK_AVOIDANCE ( & iaxsl [ callno ] ) ;
pvt = iaxs [ callno ] ;
}
if ( ! pvt - > peercallno ) {
return - 1 ;
}
}
return 0 ;
}
static int iax2_setoption ( struct ast_channel * c , int option , void * data , int datalen )
{
struct ast_option_header * h ;
@ -3493,8 +3515,23 @@ static int iax2_setoption(struct ast_channel *c, int option, void *data, int dat
errno = ENOSYS ;
return - 1 ;
default :
if ( ! ( h = ast_malloc ( datalen + sizeof ( * h ) ) ) )
{
unsigned short callno = PTR_TO_CALLNO ( c - > tech_pvt ) ;
struct chan_iax2_pvt * pvt ;
ast_mutex_lock ( & iaxsl [ callno ] ) ;
pvt = iaxs [ callno ] ;
if ( wait_for_peercallno ( pvt ) ) {
ast_mutex_unlock ( & iaxsl [ callno ] ) ;
return - 1 ;
}
ast_mutex_unlock ( & iaxsl [ callno ] ) ;
if ( ! ( h = ast_malloc ( datalen + sizeof ( * h ) ) ) ) {
return - 1 ;
}
h - > flag = AST_OPTION_FLAG_REQUEST ;
h - > option = htons ( option ) ;
@ -3505,6 +3542,7 @@ static int iax2_setoption(struct ast_channel *c, int option, void *data, int dat
free ( h ) ;
return res ;
}
}
}
static struct ast_frame * iax2_read ( struct ast_channel * c )
@ -3724,17 +3762,9 @@ static int iax2_indicate(struct ast_channel *c, int condition, const void *data,
ast_mutex_lock ( & iaxsl [ callno ] ) ;
pvt = iaxs [ callno ] ;
if ( ! pvt - > peercallno ) {
/* We don't know the remote side's call number, yet. :( */
int count = 10 ;
while ( count - - & & pvt & & ! pvt - > peercallno ) {
DEADLOCK_AVOIDANCE ( & iaxsl [ callno ] ) ;
pvt = iaxs [ callno ] ;
}
if ( ! pvt - > peercallno ) {
res = - 1 ;
goto done ;
}
if ( wait_for_peercallno ( pvt ) ) {
res = - 1 ;
goto done ;
}
switch ( condition ) {