@ -1510,6 +1510,7 @@ static int __sip_subscribe_mwi_do(struct sip_subscription_mwi *mwi);
/* Scheduler id start/stop/reschedule functions. */
static void stop_provisional_keepalive ( struct sip_pvt * pvt ) ;
static void do_stop_session_timer ( struct sip_pvt * pvt ) ;
static void stop_reinvite_retry ( struct sip_pvt * pvt ) ;
/*! \brief Definition of this channel for PBX channel registration */
struct ast_channel_tech sip_tech = {
@ -7218,7 +7219,7 @@ static int sip_hangup(struct ast_channel *ast)
but we can ' t send one while we have " INVITE " outstanding . */
ast_set_flag ( & p - > flags [ 0 ] , SIP_PENDINGBYE ) ;
ast_clear_flag ( & p - > flags [ 0 ] , SIP_NEEDREINVITE ) ;
AST_SCHED_DEL_UNREF( sched , p - > waitid , dialog_unref ( p , " when you delete the waitid sched, you should dec the refcount for the stored dialog ptr " ) ) ;
stop_reinvite_retry( p ) ;
sip_cancel_destroy ( p ) ;
/* If we have an ongoing reinvite, there is a chance that we have gotten a provisional
@ -22900,10 +22901,13 @@ static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req, char
}
}
/*! \brief Check pending actions on SIP call
/*!
* \ brief Check pending actions on SIP call
*
* \ note both sip_pvt and sip_pvt ' s owner channel ( if present )
* must be locked for this function .
*
* \ note Run by the sched thread .
*/
static void check_pendings ( struct sip_pvt * p )
{
@ -22938,7 +22942,11 @@ static void check_pendings(struct sip_pvt *p)
sip_scheddestroy ( p , DEFAULT_TRANS_TIMEOUT ) ;
} else if ( ast_test_flag ( & p - > flags [ 0 ] , SIP_NEEDREINVITE ) ) {
/* if we can't REINVITE, hold it for later */
if ( p - > pendinginvite | | p - > invitestate = = INV_CALLING | | p - > invitestate = = INV_PROCEEDING | | p - > invitestate = = INV_EARLY_MEDIA | | p - > waitid > - 1 ) {
if ( p - > pendinginvite
| | p - > invitestate = = INV_CALLING
| | p - > invitestate = = INV_PROCEEDING
| | p - > invitestate = = INV_EARLY_MEDIA
| | p - > waitid > - 1 ) {
ast_debug ( 2 , " NOT Sending pending reinvite (yet) on '%s' \n " , p - > callid ) ;
} else {
ast_debug ( 2 , " Sending pending reinvite on '%s' \n " , p - > callid ) ;
@ -22949,10 +22957,39 @@ static void check_pendings(struct sip_pvt *p)
}
}
/*! \brief Reset the NEEDREINVITE flag after waiting when we get 491 on a Re-invite
to avoid race conditions between asterisk servers .
Called from the scheduler .
*/
/* Run by the sched thread. */
static int __sched_check_pendings ( const void * data )
{
struct sip_pvt * pvt = ( void * ) data ;
struct ast_channel * owner ;
owner = sip_pvt_lock_full ( pvt ) ;
check_pendings ( pvt ) ;
if ( owner ) {
ast_channel_unlock ( owner ) ;
ast_channel_unref ( owner ) ;
}
sip_pvt_unlock ( pvt ) ;
dialog_unref ( pvt , " Check pending actions action " ) ;
return 0 ;
}
static void sched_check_pendings ( struct sip_pvt * pvt )
{
dialog_ref ( pvt , " Check pending actions action " ) ;
if ( ast_sched_add ( sched , 0 , __sched_check_pendings , pvt ) < 0 ) {
/* Uh Oh. Expect bad behavior. */
dialog_unref ( pvt , " Failed to schedule check pending actions action " ) ;
}
}
/*!
* \ brief Reset the NEEDREINVITE flag after waiting when we get 491 on a Re - invite
* to avoid race conditions between asterisk servers .
*
* \ note Run by the sched thread .
*/
static int sip_reinvite_retry ( const void * data )
{
struct sip_pvt * p = ( struct sip_pvt * ) data ;
@ -22967,10 +23004,30 @@ static int sip_reinvite_retry(const void *data)
ast_channel_unlock ( owner ) ;
ast_channel_unref ( owner ) ;
}
dialog_unref ( p , " unref the dialog ptr from sip_reinvite_retry, because it held a dialog ptr " ) ;
dialog_unref ( p , " Schedule waitid complete " ) ;
return 0 ;
}
/* Run by the sched thread. */
static int __stop_reinvite_retry ( const void * data )
{
struct sip_pvt * pvt = ( void * ) data ;
AST_SCHED_DEL_UNREF ( sched , pvt - > waitid ,
dialog_unref ( pvt , " Stop scheduled waitid " ) ) ;
dialog_unref ( pvt , " Stop reinvite retry action " ) ;
return 0 ;
}
static void stop_reinvite_retry ( struct sip_pvt * pvt )
{
dialog_ref ( pvt , " Stop reinvite retry action " ) ;
if ( ast_sched_add ( sched , 0 , __stop_reinvite_retry , pvt ) < 0 ) {
/* Uh Oh. Expect bad behavior. */
dialog_unref ( pvt , " Failed to schedule stop reinvite retry action " ) ;
}
}
/*!
* \ brief Handle authentication challenge for SIP UPDATE
*
@ -23195,7 +23252,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest
if ( ! req - > ignore & & p - > invitestate ! = INV_CANCELLED ) {
sip_cancel_destroy ( p ) ;
}
check_pendings( p ) ;
sched_ check_pendings( p ) ;
break ;
case 180 : /* 180 Ringing */
@ -23253,7 +23310,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest
}
ast_rtp_instance_activate ( p - > rtp ) ;
}
check_pendings( p ) ;
sched_ check_pendings( p ) ;
break ;
case 181 : /* Call Is Being Forwarded */
@ -23286,7 +23343,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest
ast_party_redirecting_free ( & redirecting ) ;
sip_handle_cc ( p , req , AST_CC_CCNR ) ;
}
check_pendings( p ) ;
sched_ check_pendings( p ) ;
break ;
case 183 : /* Session progress */
@ -23347,7 +23404,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest
ast_queue_control ( p - > owner , AST_CONTROL_RINGING ) ;
}
}
check_pendings( p ) ;
sched_ check_pendings( p ) ;
break ;
case 200 : /* 200 OK on invite - someone's answering our call */
@ -23497,7 +23554,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest
p - > invitestate = INV_TERMINATED ;
ast_set_flag ( & p - > flags [ 1 ] , SIP_PAGE2_DIALOG_ESTABLISHED ) ;
xmitres = transmit_request ( p , SIP_ACK , seqno , XMIT_UNRELIABLE , TRUE ) ;
check_pendings( p ) ;
sched_ check_pendings( p ) ;
break ;
case 407 : /* Proxy authentication */
@ -23609,7 +23666,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest
update_call_counter ( p , DEC_CALL_LIMIT ) ;
append_history ( p , " Hangup " , " Got 487 on CANCEL request from us on call without owner. Killing this dialog. " ) ;
}
check_pendings( p ) ;
sched_ check_pendings( p ) ;
sip_scheddestroy ( p , DEFAULT_TRANS_TIMEOUT ) ;
break ;
case 415 : /* Unsupported media type */
@ -23641,6 +23698,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest
/* Reset the flag after a while
*/
int wait ;
/* RFC 3261, if owner of call, wait between 2.1 to 4 seconds,
* if not owner of call , wait 0 to 2 seconds */
if ( p - > outgoing_call ) {
@ -23648,7 +23706,12 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest
} else {
wait = ast_random ( ) % 2000 ;
}
p - > waitid = ast_sched_add ( sched , wait , sip_reinvite_retry , dialog_ref ( p , " passing dialog ptr into sched structure based on waitid for sip_reinvite_retry. " ) ) ;
dialog_ref ( p , " Schedule waitid for sip_reinvite_retry. " ) ;
p - > waitid = ast_sched_add ( sched , wait , sip_reinvite_retry , p ) ;
if ( p - > waitid < 0 ) {
/* Uh Oh. Expect bad behavior. */
dialog_ref ( p , " Failed to schedule waitid " ) ;
}
ast_debug ( 2 , " Reinvite race. Scheduled sip_reinvite_retry in %d secs in handle_response_invite (waitid %d, dialog '%s') \n " ,
wait , p - > waitid , p - > callid ) ;
}
@ -26872,7 +26935,7 @@ static int handle_request_bye(struct sip_pvt *p, struct sip_request *req)
/* Destroy any pending invites so we won't try to do another
* scheduled reINVITE . */
AST_SCHED_DEL_UNREF( sched , p - > waitid , dialog_unref ( p , " decrement refcount from sip_destroy because waitid won't be scheduled " ) ) ;
stop_reinvite_retry( p ) ;
return 1 ;
}
@ -28404,7 +28467,7 @@ static int handle_incoming(struct sip_pvt *p, struct sip_request *req, struct as
ast_queue_control ( p - > owner , AST_CONTROL_SRCCHANGE ) ;
}
}
check_pendings( p ) ;
sched_ check_pendings( p ) ;
} else if ( p - > glareinvite = = seqno ) {
/* handle ack for the 491 pending sent for glareinvite */
p - > glareinvite = 0 ;