@ -43,7 +43,6 @@ static const char *status_map [] = {
[ UNKNOWN ] = " Unknown " ,
[ CREATED ] = " Created " ,
[ REMOVED ] = " Removed " ,
[ UPDATED ] = " Updated " ,
} ;
static const char * short_status_map [ ] = {
@ -52,7 +51,6 @@ static const char *short_status_map [] = {
[ UNKNOWN ] = " Unknown " ,
[ CREATED ] = " Created " ,
[ REMOVED ] = " Removed " ,
[ UPDATED ] = " Updated " ,
} ;
const char * ast_sip_get_contact_status_label ( const enum ast_sip_contact_status_type status )
@ -157,7 +155,7 @@ struct ast_sip_contact_status *ast_res_pjsip_find_or_create_contact_status(const
* \ brief Update an ast_sip_contact_status ' s elements .
*/
static void update_contact_status ( const struct ast_sip_contact * contact ,
enum ast_sip_contact_status_type value )
enum ast_sip_contact_status_type value , int is_contact_refresh )
{
RAII_VAR ( struct ast_sip_contact_status * , status , NULL , ao2_cleanup ) ;
RAII_VAR ( struct ast_sip_contact_status * , update , NULL , ao2_cleanup ) ;
@ -169,6 +167,26 @@ static void update_contact_status(const struct ast_sip_contact *contact,
return ;
}
if ( is_contact_refresh
& & status - > status = = CREATED ) {
/*
* The contact status hasn ' t been updated since creation
* and we don ' t want to re - send a created status .
*/
if ( contact - > qualify_frequency
| | status - > rtt_start . tv_sec > 0 ) {
/* Ignore, the status will change soon. */
return ;
}
/*
* Convert to a regular contact status update
* because the status may never change .
*/
is_contact_refresh = 0 ;
value = UNKNOWN ;
}
update = ast_sorcery_alloc ( ast_sip_get_sorcery ( ) , CONTACT_STATUS ,
ast_sorcery_object_get_id ( status ) ) ;
if ( ! update ) {
@ -178,22 +196,35 @@ static void update_contact_status(const struct ast_sip_contact *contact,
}
ast_string_field_set ( update , uri , contact - > uri ) ;
update - > last_status = status - > status ;
update - > status = value ;
/* if the contact is available calculate the rtt as
the diff between the last start time and " now " */
update - > rtt = update - > status = = AVAILABLE & & status - > rtt_start . tv_sec > 0 ?
ast_tvdiff_us ( ast_tvnow ( ) , status - > rtt_start ) : 0 ;
update - > rtt_start = ast_tv ( 0 , 0 ) ;
ast_test_suite_event_notify ( " AOR_CONTACT_QUALIFY_RESULT " ,
" Contact: %s \r \n "
" Status: %s \r \n "
" RTT: % " PRId64 ,
ast_sorcery_object_get_id ( update ) ,
ast_sip_get_contact_status_label ( update - > status ) ,
update - > rtt ) ;
if ( is_contact_refresh ) {
/* Copy everything just to set the refresh flag. */
update - > status = status - > status ;
update - > last_status = status - > last_status ;
update - > rtt = status - > rtt ;
update - > rtt_start = status - > rtt_start ;
update - > refresh = 1 ;
} else {
update - > last_status = status - > status ;
update - > status = value ;
/*
* if the contact is available calculate the rtt as
* the diff between the last start time and " now "
*/
update - > rtt = update - > status = = AVAILABLE & & status - > rtt_start . tv_sec > 0
? ast_tvdiff_us ( ast_tvnow ( ) , status - > rtt_start )
: 0 ;
update - > rtt_start = ast_tv ( 0 , 0 ) ;
ast_test_suite_event_notify ( " AOR_CONTACT_QUALIFY_RESULT " ,
" Contact: %s \r \n "
" Status: %s \r \n "
" RTT: % " PRId64 ,
ast_sorcery_object_get_id ( update ) ,
ast_sip_get_contact_status_label ( update - > status ) ,
update - > rtt ) ;
}
if ( ast_sorcery_update ( ast_sip_get_sorcery ( ) , update ) ) {
ast_log ( LOG_ERROR , " Unable to update ast_sip_contact_status for contact %s \n " ,
@ -306,10 +337,10 @@ static void qualify_contact_cb(void *token, pjsip_event *e)
/* Fall through */
case PJSIP_EVENT_TRANSPORT_ERROR :
case PJSIP_EVENT_TIMER :
update_contact_status ( contact , UNAVAILABLE );
update_contact_status ( contact , UNAVAILABLE , 0 );
break ;
case PJSIP_EVENT_RX_MSG :
update_contact_status ( contact , AVAILABLE );
update_contact_status ( contact , AVAILABLE , 0 );
break ;
}
ao2_cleanup ( contact ) ;
@ -365,7 +396,7 @@ static int qualify_contact(struct ast_sip_endpoint *endpoint, struct ast_sip_con
! = PJ_SUCCESS ) {
ast_log ( LOG_ERROR , " Unable to send request to qualify contact %s \n " ,
contact - > uri ) ;
update_contact_status ( contact , UNAVAILABLE );
update_contact_status ( contact , UNAVAILABLE , 0 );
ao2_ref ( contact , - 1 ) ;
return - 1 ;
}
@ -525,7 +556,7 @@ static void qualify_and_schedule(struct ast_sip_contact *contact)
schedule_qualify ( contact , contact - > qualify_frequency * 1000 ) ;
} else {
update_contact_status ( contact , UNKNOWN );
update_contact_status ( contact , UNKNOWN , 0 );
}
}
@ -544,8 +575,7 @@ static void contact_created(const void *obj)
*/
static void contact_updated ( const void * obj )
{
update_contact_status ( ( struct ast_sip_contact * ) obj , UPDATED ) ;
qualify_and_schedule ( ( struct ast_sip_contact * ) obj ) ;
update_contact_status ( obj , AVAILABLE , 1 ) ;
}
/*!
@ -574,8 +604,8 @@ static void contact_deleted(const void *obj)
static const struct ast_sorcery_observer contact_observer = {
. created = contact_created ,
. updated = contact_updated ,
. deleted = contact_deleted ,
. updated = contact_updated
} ;
static pj_bool_t options_start ( void )
@ -1051,7 +1081,7 @@ static void qualify_and_schedule_contact(struct ast_sip_contact *contact)
if ( contact - > qualify_frequency ) {
schedule_qualify ( contact , initial_interval ) ;
} else {
update_contact_status ( contact , UNKNOWN );
update_contact_status ( contact , UNKNOWN , 0 );
}
}