@ -181,7 +181,7 @@ struct ast_sip_contact *ast_sip_location_retrieve_contact(const char *contact_na
int ast_sip_location_add_contact ( struct ast_sip_aor * aor , const char * uri ,
struct timeval expiration_time , const char * path_info , const char * user_agent )
{
char name [ AST_UUID_STR_LEN ] ;
char name [ MAX_OBJECT_FIELD * 2 + 3 ] ;
RAII_VAR ( struct ast_sip_contact * , contact , NULL , ao2_cleanup ) ;
snprintf ( name , sizeof ( name ) , " %s;@%s " , ast_sorcery_object_get_id ( aor ) , uri ) ;
@ -279,21 +279,21 @@ static int permanent_uri_handler(const struct aco_option *opt, struct ast_variab
return 0 ;
}
static int contact_to_v l( void * object , void * arg , int flags )
static int contact_to_v ar_ list ( void * object , void * arg , int flags )
{
struct ast_sip_contact * contact = object ;
struct ast_sip_contact _wrapper * wrapper = object ;
struct ast_variable * * var = arg ;
ast_variable_list_append ( & * var , ast_variable_new ( " contact " , contact- > uri , " " ) ) ;
ast_variable_list_append ( & * var , ast_variable_new ( " contact " , wrapper- > contact- > uri , " " ) ) ;
return 0 ;
}
static int contacts_to_v l( const void * obj , struct ast_variable * * fields )
static int contacts_to_v ar_ list ( const void * obj , struct ast_variable * * fields )
{
const struct ast_sip_aor * aor = obj ;
ast_sip_for_each_contact ( aor , contact_to_v l, fields ) ;
ast_sip_for_each_contact ( aor , contact_to_v ar_ list , fields ) ;
return 0 ;
}
@ -323,12 +323,21 @@ int ast_sip_for_each_aor(const char *aors, ao2_callback_fn on_aor, void *arg)
return 0 ;
}
static void contact_wrapper_destroy ( void * obj )
{
struct ast_sip_contact_wrapper * wrapper = obj ;
ast_free ( wrapper - > aor_id ) ;
ast_free ( wrapper - > contact_id ) ;
ao2_ref ( wrapper - > contact , - 1 ) ;
}
int ast_sip_for_each_contact ( const struct ast_sip_aor * aor ,
ao2_callback_fn on_contact , void * arg )
{
RAII_VAR ( struct ao2_container * , contacts , NULL , ao2_cleanup ) ;
struct ast_sip_contact * contact ;
struct ao2_iterator i ;
int res = 0 ;
void * object = NULL ;
if ( ! on_contact | |
! ( contacts = ast_sip_location_retrieve_aor_contacts ( aor ) ) ) {
@ -336,26 +345,44 @@ int ast_sip_for_each_contact(const struct ast_sip_aor *aor,
}
i = ao2_iterator_init ( contacts , 0 ) ;
while ( ( contact = ao2_iterator_next ( & i ) ) ) {
int res ;
while ( ( object = ao2_iterator_next ( & i ) ) ) {
RAII_VAR ( struct ast_sip_contact * , contact , object , ao2_cleanup ) ;
RAII_VAR ( struct ast_sip_contact_wrapper * , wrapper , NULL , ao2_cleanup ) ;
const char * aor_id = ast_sorcery_object_get_id ( aor ) ;
wrapper = ao2_alloc ( sizeof ( struct ast_sip_contact_wrapper ) , contact_wrapper_destroy ) ;
if ( ! wrapper ) {
res = - 1 ;
break ;
}
wrapper - > contact_id = ast_malloc ( strlen ( aor_id ) + strlen ( contact - > uri ) + 2 ) ;
if ( ! wrapper - > contact_id ) {
res = - 1 ;
break ;
}
sprintf ( wrapper - > contact_id , " %s/%s " , aor_id , contact - > uri ) ;
wrapper - > aor_id = ast_strdup ( aor_id ) ;
if ( ! wrapper - > aor_id ) {
res = - 1 ;
break ;
}
wrapper - > contact = contact ;
ao2_bump ( wrapper - > contact ) ;
ast_sorcery_object_set_extended ( contact , " @aor_id " , ast_sorcery_object_get_id ( aor ) ) ;
if ( ( res = on_contact ( contact , arg , 0 ) ) ) {
ao2_iterator_destroy ( & i ) ;
return - 1 ;
if ( ( res = on_contact ( wrapper , arg , 0 ) ) ) {
break ;
}
}
ao2_iterator_destroy ( & i ) ;
return 0 ;
return res ;
}
int ast_sip_contact_to_str ( void * object , void * arg , int flags )
{
struct ast_sip_contact * contact = object ;
struct ast_sip_contact _wrapper * wrapper = object ;
struct ast_str * * buf = arg ;
ast_str_append ( buf , 0 , " %s/%s, " ,
ast_sorcery_object_get_extended ( contact , " aor_id " ) , contact - > uri ) ;
ast_str_append ( buf , 0 , " %s, " , wrapper - > contact_id ) ;
return 0 ;
}
@ -448,10 +475,10 @@ struct ast_sip_endpoint_formatter endpoint_aor_formatter = {
. format_ami = format_ami_endpoint_aor
} ;
static struct ao2_container * cli_ get_ aor_container( void )
static struct ao2_container * cli_ aor_get _container( void )
{
RAII_VAR ( struct ao2_container * , container , NULL , ao2_cleanup ) ;
RAII_VAR ( struct ao2_container * , s_container , NULL , ao2_cleanup ) ;
struct ao2_container * s_container ;
container = ast_sorcery_retrieve_by_fields ( ast_sip_get_sorcery ( ) , " aor " ,
AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL , NULL ) ;
@ -460,90 +487,144 @@ static struct ao2_container *cli_get_aor_container(void)
}
s_container = ao2_container_alloc_list ( AO2_ALLOC_OPT_LOCK_NOLOCK , 0 ,
ast_sorcery_object_id_ compare, NULL ) ;
ast_sorcery_object_id_ sort, ast_sorcery_object_id_compare ) ;
if ( ! s_container ) {
return NULL ;
}
if ( ao2_container_dup ( s_container , container , 0 ) ) {
ao2_ref ( s_container , - 1 ) ;
return NULL ;
}
ao2_ref ( s_container , + 1 ) ;
return s_container ;
}
static int populate_contact _container( void * obj , void * arg , int flags )
static int cli_contact_populate _container( void * obj , void * arg , int flags )
{
struct ast_sip_contact * contact = obj ;
struct ao2_container * container = arg ;
ao2_link ( arg , obj ) ;
ao2_link ( container , contact ) ;
return 0 ;
}
static int gather_ao r_contacts( void * obj , void * arg , int flags )
static int cli_aor_ gather_contacts( void * obj , void * arg , int flags )
{
struct ast_sip_aor * aor = obj ;
struct ao2_container * container = arg ;
ast_sip_for_each_contact ( aor , populate_contact_container , container ) ;
return 0 ;
return ast_sip_for_each_contact ( aor , cli_contact_populate_container , arg ) ;
}
static int cli_contact_compare ( const void * left , const void * right , int flags )
static const char * cli_contact_get_id ( const void * obj )
{
const struct ast_sip_contact * left_contact = left ;
const struct ast_sip_contact * right_contact = right ;
int rc ;
const struct ast_sip_contact _wrapper * wrapper = obj ;
return wrapper - > contact_id ;
}
if ( ! left_contact | | ! right_contact ) {
return 0 ;
static int cli_contact_sort ( const void * obj , const void * arg , int flags )
{
const struct ast_sip_contact_wrapper * left_wrapper = obj ;
const struct ast_sip_contact_wrapper * right_wrapper = arg ;
const char * right_key = arg ;
int cmp = 0 ;
switch ( flags & OBJ_SEARCH_MASK ) {
case OBJ_SEARCH_OBJECT :
right_key = right_wrapper - > contact_id ;
/* Fall through */
case OBJ_SEARCH_KEY :
cmp = strcmp ( left_wrapper - > contact_id , right_key ) ;
break ;
case OBJ_SEARCH_PARTIAL_KEY :
cmp = strncmp ( left_wrapper - > contact_id , right_key , strlen ( right_key ) ) ;
break ;
default :
cmp = 0 ;
break ;
}
rc = strcmp ( ast_sorcery_object_get_extended ( left_contact , " aor_id " ) ,
ast_sorcery_object_get_extended ( right_contact , " aor_id " ) ) ;
if ( rc ) {
return rc ;
return cmp ;
}
static int cli_contact_compare ( void * obj , void * arg , int flags )
{
const struct ast_sip_contact_wrapper * left_wrapper = obj ;
const struct ast_sip_contact_wrapper * right_wrapper = arg ;
const char * right_key = arg ;
int cmp = 0 ;
switch ( flags & OBJ_SEARCH_MASK ) {
case OBJ_SEARCH_OBJECT :
right_key = right_wrapper - > contact_id ;
/* Fall through */
case OBJ_SEARCH_KEY :
if ( strcmp ( left_wrapper - > contact_id , right_key ) = = 0 ) { ;
cmp = CMP_MATCH | CMP_STOP ;
}
break ;
case OBJ_SEARCH_PARTIAL_KEY :
if ( strncmp ( left_wrapper - > contact_id , right_key , strlen ( right_key ) ) = = 0 ) {
cmp = CMP_MATCH ;
}
break ;
default :
cmp = 0 ;
break ;
}
return cmp ;
}
static int cli_contact_hash ( const void * obj , int flags )
{
const struct ast_sip_contact_wrapper * wrapper = obj ;
if ( flags & OBJ_SEARCH_OBJECT ) {
return ast_str_hash ( wrapper - > contact_id ) ;
} else if ( flags & OBJ_SEARCH_KEY ) {
return ast_str_hash ( obj ) ;
}
return strcmp ( left_contact - > uri , right_contact - > uri ) ;
return - 1 ;
}
static int cli_contact_iterate ( void * container , ao2_callback_fn callback , void * args )
{
return ast_sip_for_each_contact ( container , callback , args ) ;
}
static struct ao2_container * cli_get_contact_container ( void )
static struct ao2_container * cli_ contact_ge t_container( void )
{
RAII_VAR ( struct ao2_container * , parent_container , NULL , ao2_cleanup ) ;
struct ao2_container * child_container ;
parent_container = cli_get_aor_container ( ) ;
parent_container = cli_ aor_get _container( ) ;
if ( ! parent_container ) {
return NULL ;
}
child_container = ao2_container_alloc_list ( AO2_ALLOC_OPT_LOCK_NOLOCK , 0 ,
cli_contact_compare , NULL ) ;
child_container = ao2_container_alloc_ hash ( AO2_ALLOC_OPT_LOCK_NOLOCK , 0 , 17 ,
cli_contact_ hash, cli_contact_sort , cli_contact_compare ) ;
if ( ! child_container ) {
return NULL ;
}
ao2_ref ( child_container , + 1 ) ;
ao2_callback ( parent_container , OBJ_NODATA , gather_aor_contacts , child_container ) ;
ao2_callback ( parent_container , OBJ_NODATA , cli_aor_gather_contacts , child_container ) ;
return child_container ;
}
static int cli_contact_iterator ( const void * container , ao2_callback_fn callback , void * args )
static void * cli_contact_retrieve_by_id ( const char * id )
{
const struct ast_sip_aor * array = container ;
return ast_sip_for_each_contact ( array , callback , args ) ;
return ao2_find ( cli_contact_get_container ( ) , id , OBJ_KEY | OBJ_NOLOCK ) ;
}
static int cli_print_contact_header ( void * obj , void * arg , int flags )
static int cli_ contact_prin t_header( void * obj , void * arg , int flags )
{
struct ast_sip_cli_context * context = arg ;
int indent = CLI_INDENT_TO_SPACES ( context - > indent_level ) ;
int filler = CLI_LAST_TABSTOP - indent - 18 ;
if ( ! context - > output_buffer ) {
return - 1 ;
}
ast_assert ( context - > output_buffer ! = NULL ) ;
ast_str_append ( & context - > output_buffer , 0 ,
" %*s: <Aor/ContactUri%*.*s> <Status....> <RTT(ms)..> \n " ,
indent , " Contact " , filler , filler , CLI_HEADER_FILLER ) ;
@ -551,27 +632,20 @@ static int cli_print_contact_header(void *obj, void *arg, int flags)
return 0 ;
}
static int cli_ print_ contact_body( void * obj , void * arg , int flags )
static int cli_ contact_prin t_body( void * obj , void * arg , int flags )
{
struct ast_sip_contact * contact = obj ;
struct ast_sip_contact_wrapper * wrapper = obj ;
struct ast_sip_contact * contact = wrapper - > contact ;
struct ast_sip_cli_context * context = arg ;
char * print_name = NULL ;
int print_name_len ;
int indent ;
int flexwidth ;
const char * aor_id = ast_sorcery_object_get_extended ( contact , " aor_id " ) ;
RAII_VAR ( struct ast_sip_contact_status * , status ,
ast_sorcery_retrieve_by_id ( ast_sip_get_sorcery ( ) , CONTACT_STATUS , ast_sorcery_object_get_id ( contact ) ) ,
ao2_cleanup ) ;
if ( ! context - > output_buffer ) {
return - 1 ;
}
print_name_len = strlen ( aor_id ) + strlen ( contact - > uri ) + 2 ;
print_name = ast_alloca ( print_name_len ) ;
snprintf ( print_name , print_name_len , " %s/%s " , aor_id , contact - > uri ) ;
ast_assert ( contact - > uri ! = NULL ) ;
ast_assert ( context - > output_buffer ! = NULL ) ;
indent = CLI_INDENT_TO_SPACES ( context - > indent_level ) ;
flexwidth = CLI_LAST_TABSTOP - indent - 2 ;
@ -580,31 +654,40 @@ static int cli_print_contact_body(void *obj, void *arg, int flags)
indent ,
" Contact " ,
flexwidth , flexwidth ,
print_name ,
wrapper- > contact_id ,
( status ? ( status - > status = = AVAILABLE ? " Avail " : " Unavail " ) : " Unknown " ) ,
( status ? ( ( long long ) status - > rtt ) / 1000.0 : NAN ) ) ;
return 0 ;
}
static int cli_aor_iterat or( const void * container , ao2_callback_fn callback , void * args )
static int cli_aor_iterat e( void * container , ao2_callback_fn callback , void * args )
{
const char * aor_list = container ;
return ast_sip_for_each_aor ( aor_list , callback , args ) ;
}
static int cli_print_aor_header ( void * obj , void * arg , int flags )
static void * cli_aor_retrieve_by_id ( const char * id )
{
return ast_sorcery_retrieve_by_id ( ast_sip_get_sorcery ( ) , " aor " , id ) ;
}
static const char * cli_aor_get_id ( const void * obj )
{
return ast_sorcery_object_get_id ( obj ) ;
}
static int cli_aor_print_header ( void * obj , void * arg , int flags )
{
struct ast_sip_cli_context * context = arg ;
struct ast_sip_cli_formatter_entry * formatter_entry ;
RAII_VAR ( struct ast_sip_cli_formatter_entry * , formatter_entry , NULL , ao2_cleanup ) ;
int indent = CLI_INDENT_TO_SPACES ( context - > indent_level ) ;
int filler = CLI_LAST_TABSTOP - indent - 7 ;
if ( ! context - > output_buffer ) {
return - 1 ;
}
ast_assert ( context - > output_buffer ! = NULL ) ;
ast_str_append ( & context - > output_buffer , 0 ,
" %*s: <Aor%*.*s> <MaxContact> \n " ,
indent , " Aor " , filler , filler , CLI_HEADER_FILLER ) ;
@ -612,27 +695,26 @@ static int cli_print_aor_header(void *obj, void *arg, int flags)
if ( context - > recurse ) {
context - > indent_level + + ;
formatter_entry = ast_sip_lookup_cli_formatter ( " contact " ) ;
if ( formatter_entry & & formatter_entry - > print_header ) {
if ( formatter_entry ) {
formatter_entry - > print_header ( NULL , context , 0 ) ;
}
context - > indent_level - - ;
}
return 0 ;
}
static int cli_ print_aor _body( void * obj , void * arg , int flags )
static int cli_ aor_ print_body( void * obj , void * arg , int flags )
{
struct ast_sip_aor * aor = obj ;
struct ast_sip_cli_context * context = arg ;
struct ast_sip_cli_formatter_entry * formatter_entry ;
RAII_VAR ( struct ast_sip_cli_formatter_entry * , formatter_entry , NULL , ao2_cleanup ) ;
int indent ;
int flexwidth ;
if ( ! context - > output_buffer ) {
return - 1 ;
}
ast_assert ( context - > output_buffer ! = NULL ) ;
context - > current_aor = aor ;
// context->current_aor = aor;
indent = CLI_INDENT_TO_SPACES ( context - > indent_level ) ;
flexwidth = CLI_LAST_TABSTOP - indent - 12 ;
@ -647,8 +729,8 @@ static int cli_print_aor_body(void *obj, void *arg, int flags)
context - > indent_level + + ;
formatter_entry = ast_sip_lookup_cli_formatter ( " contact " ) ;
if ( formatter_entry & & formatter_entry - > print_body & & formatter_entry - > iterator ) {
formatter_entry - > iterat or ( aor , formatter_entry - > print_body , context ) ;
if ( formatter_entry ) {
formatter_entry - > iterat e ( aor , formatter_entry - > print_body , context ) ;
}
context - > indent_level - - ;
@ -666,24 +748,6 @@ static int cli_print_aor_body(void *obj, void *arg, int flags)
return 0 ;
}
static struct ast_sip_cli_formatter_entry cli_contact_formatter = {
. name = " contact " ,
. print_header = cli_print_contact_header ,
. print_body = cli_print_contact_body ,
. get_container = cli_get_contact_container ,
. iterator = cli_contact_iterator ,
. comparator = cli_contact_compare ,
} ;
static struct ast_sip_cli_formatter_entry cli_aor_formatter = {
. name = " aor " ,
. print_header = cli_print_aor_header ,
. print_body = cli_print_aor_body ,
. get_container = cli_get_aor_container ,
. iterator = cli_aor_iterator ,
. comparator = ast_sorcery_object_id_compare ,
} ;
static struct ast_cli_entry cli_commands [ ] = {
AST_CLI_DEFINE ( ast_sip_cli_traverse_objects , " List PJSIP Aors " ,
. command = " pjsip list aors " ,
@ -706,8 +770,15 @@ static struct ast_cli_entry cli_commands[] = {
. command = " pjsip show contacts " ,
. usage = " Usage: pjsip show contacts \n "
" Show the configured PJSIP contacts \n " ) ,
AST_CLI_DEFINE ( ast_sip_cli_traverse_objects , " Show PJSIP Contact " ,
. command = " pjsip show contact " ,
. usage = " Usage: pjsip show contact \n "
" Show the configured PJSIP contact \n " ) ,
} ;
struct ast_sip_cli_formatter_entry * contact_formatter ;
struct ast_sip_cli_formatter_entry * aor_formatter ;
/*! \brief Initialize sorcery with location support */
int ast_sip_initialize_sorcery_location ( void )
{
@ -737,23 +808,52 @@ int ast_sip_initialize_sorcery_location(void)
ast_sorcery_object_field_register ( sorcery , " aor " , " authenticate_qualify " , " no " , OPT_BOOL_T , 1 , FLDSET ( struct ast_sip_aor , authenticate_qualify ) ) ;
ast_sorcery_object_field_register ( sorcery , " aor " , " max_contacts " , " 0 " , OPT_UINT_T , 0 , FLDSET ( struct ast_sip_aor , max_contacts ) ) ;
ast_sorcery_object_field_register ( sorcery , " aor " , " remove_existing " , " no " , OPT_BOOL_T , 1 , FLDSET ( struct ast_sip_aor , remove_existing ) ) ;
ast_sorcery_object_field_register_custom ( sorcery , " aor " , " contact " , " " , permanent_uri_handler , contacts_to_str , contacts_to_v l, 0 , 0 ) ;
ast_sorcery_object_field_register_custom ( sorcery , " aor " , " contact " , " " , permanent_uri_handler , contacts_to_str , contacts_to_v ar_ list , 0 , 0 ) ;
ast_sorcery_object_field_register ( sorcery , " aor " , " mailboxes " , " " , OPT_STRINGFIELD_T , 0 , STRFLDSET ( struct ast_sip_aor , mailboxes ) ) ;
ast_sorcery_object_field_register ( sorcery , " aor " , " outbound_proxy " , " " , OPT_STRINGFIELD_T , 0 , STRFLDSET ( struct ast_sip_aor , outbound_proxy ) ) ;
ast_sorcery_object_field_register ( sorcery , " aor " , " support_path " , " no " , OPT_BOOL_T , 1 , FLDSET ( struct ast_sip_aor , support_path ) ) ;
ast_sip_register_endpoint_formatter ( & endpoint_aor_formatter ) ;
ast_sip_register_cli_formatter ( & cli_contact_formatter ) ;
ast_sip_register_cli_formatter ( & cli_aor_formatter ) ;
contact_formatter = ao2_alloc ( sizeof ( struct ast_sip_cli_formatter_entry ) , NULL ) ;
if ( ! contact_formatter ) {
ast_log ( LOG_ERROR , " Unable to allocate memory for contact_formatter \n " ) ;
return - 1 ;
}
contact_formatter - > name = " contact " ;
contact_formatter - > print_header = cli_contact_print_header ;
contact_formatter - > print_body = cli_contact_print_body ;
contact_formatter - > get_container = cli_contact_get_container ;
contact_formatter - > iterate = cli_contact_iterate ;
contact_formatter - > get_id = cli_contact_get_id ;
contact_formatter - > retrieve_by_id = cli_contact_retrieve_by_id ;
aor_formatter = ao2_alloc ( sizeof ( struct ast_sip_cli_formatter_entry ) , NULL ) ;
if ( ! aor_formatter ) {
ast_log ( LOG_ERROR , " Unable to allocate memory for aor_formatter \n " ) ;
return - 1 ;
}
aor_formatter - > name = " aor " ;
aor_formatter - > print_header = cli_aor_print_header ;
aor_formatter - > print_body = cli_aor_print_body ;
aor_formatter - > get_container = cli_aor_get_container ;
aor_formatter - > iterate = cli_aor_iterate ;
aor_formatter - > get_id = cli_aor_get_id ;
aor_formatter - > retrieve_by_id = cli_aor_retrieve_by_id ;
ast_sip_register_cli_formatter ( contact_formatter ) ;
ast_sip_register_cli_formatter ( aor_formatter ) ;
ast_cli_register_multiple ( cli_commands , ARRAY_LEN ( cli_commands ) ) ;
return 0 ;
}
int ast_sip_destroy_sorcery_location ( void )
{
ast_cli_unregister_multiple ( cli_commands , ARRAY_LEN ( cli_commands ) ) ;
ast_sip_unregister_cli_formatter ( & cli_contact_formatter ) ;
ast_sip_unregister_cli_formatter ( & cli_aor_formatter ) ;
ast_sip_unregister_cli_formatter ( contact_formatter ) ;
ast_sip_unregister_cli_formatter ( aor_formatter ) ;
return 0 ;
}