@ -820,6 +820,15 @@ struct chan_iax2_pvt {
int frames_received ;
/*! num bytes used for calltoken ie, even an empty ie should contain 2 */
unsigned char calltoken_ie_len ;
/*! hold all signaling frames from the pbx thread until we have a destination callno */
char hold_signaling ;
/*! frame queue for signaling frames from pbx thread waiting for destination callno */
AST_LIST_HEAD_NOLOCK ( signaling_queue , signaling_queue_entry ) signaling_queue ;
} ;
struct signaling_queue_entry {
struct ast_frame f ;
AST_LIST_ENTRY ( signaling_queue_entry ) next ;
} ;
/*! table of available call numbers */
@ -1703,10 +1712,56 @@ static int scheduled_destroy(const void *vid)
return 0 ;
}
static void free_signaling_queue_entry ( struct signaling_queue_entry * s )
{
ast_free ( s - > f . data . ptr ) ;
ast_free ( s ) ;
}
/*! \brief This function must be called once we are sure the other side has
* given us a call number . All signaling is held here until that point . */
static void send_signaling ( struct chan_iax2_pvt * pvt )
{
struct signaling_queue_entry * s = NULL ;
while ( ( s = AST_LIST_REMOVE_HEAD ( & pvt - > signaling_queue , next ) ) ) {
iax2_send ( pvt , & s - > f , 0 , - 1 , 0 , 0 , 0 ) ;
free_signaling_queue_entry ( s ) ;
}
pvt - > hold_signaling = 0 ;
}
/*! \brief All frames other than that of type AST_FRAME_IAX must be held until
* we have received a destination call number . */
static int queue_signalling ( struct chan_iax2_pvt * pvt , struct ast_frame * f )
{
struct signaling_queue_entry * new ;
if ( f - > frametype = = AST_FRAME_IAX | | ! pvt - > hold_signaling ) {
return 1 ; /* do not queue this frame */
} else if ( ! ( new = ast_calloc ( 1 , sizeof ( struct signaling_queue_entry ) ) ) ) {
return - 1 ; /* out of memory */
}
memcpy ( & new - > f , f , sizeof ( new - > f ) ) ; /* copy ast_frame into our queue entry */
if ( new - > f . datalen ) { /* if there is data in this frame copy it over as well */
if ( ! ( new - > f . data . ptr = ast_calloc ( 1 , new - > f . datalen ) ) ) {
free_signaling_queue_entry ( new ) ;
return - 1 ;
}
memcpy ( new - > f . data . ptr , f - > data . ptr , sizeof ( * new - > f . data . ptr ) ) ;
}
AST_LIST_INSERT_TAIL ( & pvt - > signaling_queue , new , next ) ;
return 0 ;
}
static void pvt_destructor ( void * obj )
{
struct chan_iax2_pvt * pvt = obj ;
struct iax_frame * cur = NULL ;
struct signaling_queue_entry * s = NULL ;
ast_mutex_lock ( & iaxsl [ pvt - > callno ] ) ;
@ -1725,6 +1780,10 @@ static void pvt_destructor(void *obj)
ast_mutex_unlock ( & iaxsl [ pvt - > callno ] ) ;
while ( ( s = AST_LIST_REMOVE_HEAD ( & pvt - > signaling_queue , next ) ) ) {
free_signaling_queue_entry ( s ) ;
}
if ( pvt - > reg ) {
pvt - > reg - > callno = 0 ;
}
@ -1781,6 +1840,9 @@ static struct chan_iax2_pvt *new_iax(struct sockaddr_in *sin, const char *host)
AST_LIST_HEAD_INIT_NOLOCK ( & tmp - > dpentries ) ;
tmp - > hold_signaling = 1 ;
AST_LIST_HEAD_INIT_NOLOCK ( & tmp - > signaling_queue ) ;
return tmp ;
}
@ -7148,6 +7210,7 @@ static int __send_command(struct chan_iax2_pvt *i, char type, int command, unsig
int now , int transfer , int final )
{
struct ast_frame f = { 0 , } ;
int res = 0 ;
f . frametype = type ;
f . subclass = command ;
@ -7155,6 +7218,10 @@ static int __send_command(struct chan_iax2_pvt *i, char type, int command, unsig
f . src = __FUNCTION__ ;
f . data . ptr = ( void * ) data ;
if ( ( res = queue_signalling ( i , & f ) ) < = 0 ) {
return res ;
}
return iax2_send ( i , & f , ts , seqno , now , transfer , final ) ;
}
@ -9634,19 +9701,15 @@ static int socket_process(struct iax2_thread *thread)
int check_dcallno = 0 ;
/*
* We enforce accurate destination call numbers for all full frames except
* LAGRQ and PING commands . This is because older versions of Asterisk
* schedule these commands to get sent very quickly , and they will sometimes
* be sent before they receive the first frame from the other side . When
* that happens , it doesn ' t contain the destination call number . However ,
* not checking it for these frames is safe .
*
* We enforce accurate destination call numbers for ACKs . This forces the other
* end to know the destination call number before call setup can complete .
*
* Discussed in the following thread :
* http : //lists.digium.com/pipermail/asterisk-dev/2008-May/033217.html
*/
if ( ntohs ( mh - > callno ) & IAX_FLAG_FULL ) {
check_dcallno = f . frametype = = AST_FRAME_IAX ? ( f . subclass ! = IAX_COMMAND_PING & & f . subclass ! = IAX_COMMAND_LAGRQ ) : 1 ;
if ( ( ntohs ( mh - > callno ) & IAX_FLAG_FULL ) & & ( ( f . frametype = = AST_FRAME_IAX ) & & ( f . subclass = = IAX_COMMAND_ACK ) ) ) {
check_dcallno = 1 ;
}
if ( ! ( fr - > callno = find_callno ( ntohs ( mh - > callno ) & ~ IAX_FLAG_FULL , dcallno , & sin , new , fd , check_dcallno ) ) ) {
@ -9922,6 +9985,12 @@ static int socket_process(struct iax2_thread *thread)
}
}
/* once we receive our first IAX Full Frame that is not CallToken related, send all
* queued signaling frames that were being held . */
if ( ( f . frametype = = AST_FRAME_IAX ) & & ( f . subclass ! = IAX_COMMAND_CALLTOKEN ) & & iaxs [ fr - > callno ] - > hold_signaling ) {
send_signaling ( iaxs [ fr - > callno ] ) ;
}
if ( f . frametype = = AST_FRAME_VOICE ) {
if ( f . subclass ! = iaxs [ fr - > callno ] - > voiceformat ) {
iaxs [ fr - > callno ] - > voiceformat = f . subclass ;