@ -132,6 +132,11 @@
and therefore the subscription must be deleted after an asterisk restart .
< / synopsis >
< / configOption >
< configOption name = " generator_data " >
< synopsis > If set , contains persistence data for all generators of content
for the subscription .
< / synopsis >
< / configOption >
< / configObject >
< configObject name = " resource_list " >
< synopsis > Resource list configuration parameters . < / synopsis >
@ -389,6 +394,8 @@ struct subscription_persistence {
char contact_uri [ PJSIP_MAX_URL_SIZE ] ;
/*! Prune subscription on restart */
int prune_on_boot ;
/*! Body generator specific persistence data */
struct ast_json * generator_data ;
} ;
/*!
@ -490,6 +497,8 @@ struct ast_sip_subscription {
unsigned int full_state ;
/*! URI associated with the subscription */
pjsip_sip_uri * uri ;
/*! Data to be persisted with the subscription */
struct ast_json * persistence_data ;
/*! Name of resource being subscribed to */
char resource [ 0 ] ;
} ;
@ -615,6 +624,7 @@ static void subscription_persistence_destroy(void *obj)
ast_free ( persistence - > endpoint ) ;
ast_free ( persistence - > tag ) ;
ast_json_unref ( persistence - > generator_data ) ;
}
/*! \brief Allocator for subscription persistence */
@ -1220,6 +1230,7 @@ static void destroy_subscription(struct ast_sip_subscription *sub)
AST_VECTOR_FREE ( & sub - > children ) ;
ao2_cleanup ( sub - > datastores ) ;
ast_json_unref ( sub - > persistence_data ) ;
ast_free ( sub ) ;
}
@ -1271,6 +1282,14 @@ static struct ast_sip_subscription *allocate_subscription(const struct ast_sip_s
pjsip_sip_uri_assign ( tree - > dlg - > pool , sub - > uri , contact_uri ) ;
pj_strdup2 ( tree - > dlg - > pool , & sub - > uri - > user , resource ) ;
/* If there is any persistence information available for this subscription that was persisted
* then make it available so that the NOTIFY has the correct state .
*/
if ( tree - > persistence & & tree - > persistence - > generator_data ) {
sub - > persistence_data = ast_json_object_get ( tree - > persistence - > generator_data , resource ) ;
}
sub - > handler = handler ;
sub - > subscription_state = PJSIP_EVSUB_STATE_ACTIVE ;
sub - > tree = ao2_bump ( tree ) ;
@ -1469,11 +1488,10 @@ static struct sip_subscription_tree *allocate_subscription_tree(struct ast_sip_e
static struct sip_subscription_tree * create_subscription_tree ( const struct ast_sip_subscription_handler * handler ,
struct ast_sip_endpoint * endpoint , pjsip_rx_data * rdata , const char * resource ,
struct ast_sip_pubsub_body_generator * generator , struct resource_tree * tree ,
pj_status_t * dlg_status )
pj_status_t * dlg_status , struct subscription_persistence * persistence )
{
struct sip_subscription_tree * sub_tree ;
pjsip_dialog * dlg ;
struct subscription_persistence * persistence ;
sub_tree = allocate_subscription_tree ( endpoint , rdata ) ;
if ( ! sub_tree ) {
@ -1514,6 +1532,9 @@ static struct sip_subscription_tree *create_subscription_tree(const struct ast_s
sub_tree - > notification_batch_interval = tree - > notification_batch_interval ;
/* Persistence information needs to be available for all the subscriptions */
sub_tree - > persistence = ao2_bump ( persistence ) ;
sub_tree - > root = create_virtual_subscriptions ( handler , resource , generator , sub_tree , tree - > root ) ;
if ( AST_VECTOR_SIZE ( & sub_tree - > root - > children ) > 0 ) {
sub_tree - > is_list = 1 ;
@ -1635,7 +1656,7 @@ static int sub_persistence_recreate(void *obj)
pj_status_t dlg_status ;
sub_tree = create_subscription_tree ( handler , endpoint , rdata , resource , generator ,
& tree , & dlg_status );
& tree , & dlg_status , persistence );
if ( ! sub_tree ) {
if ( dlg_status ! = PJ_EEXISTS ) {
ast_log ( LOG_WARNING , " Failed recreating '%s' subscription: Could not create subscription tree. \n " ,
@ -1653,7 +1674,6 @@ static int sub_persistence_recreate(void *obj)
ind - > sub_tree = ao2_bump ( sub_tree ) ;
ind - > expires = expires_header - > ivalue ;
sub_tree - > persistence = ao2_bump ( persistence ) ;
subscription_persistence_update ( sub_tree , rdata , SUBSCRIPTION_PERSISTENCE_RECREATED ) ;
if ( ast_sip_push_task ( sub_tree - > serializer , initial_notify_task , ind ) ) {
/* Could not send initial subscribe NOTIFY */
@ -2710,6 +2730,28 @@ void ast_sip_publication_remove_datastore(struct ast_sip_publication *publicatio
ao2_callback ( publication - > datastores , OBJ_KEY | OBJ_UNLINK | OBJ_NODATA , NULL , ( void * ) name ) ;
}
void ast_sip_subscription_set_persistence_data ( struct ast_sip_subscription * subscription , struct ast_json * persistence_data )
{
ast_json_unref ( subscription - > persistence_data ) ;
subscription - > persistence_data = persistence_data ;
if ( subscription - > tree - > persistence ) {
if ( ! subscription - > tree - > persistence - > generator_data ) {
subscription - > tree - > persistence - > generator_data = ast_json_object_create ( ) ;
if ( ! subscription - > tree - > persistence - > generator_data ) {
return ;
}
}
ast_json_object_set ( subscription - > tree - > persistence - > generator_data , subscription - > resource ,
ast_json_ref ( persistence_data ) ) ;
}
}
const struct ast_json * ast_sip_subscription_get_persistence_data ( const struct ast_sip_subscription * subscription )
{
return subscription - > persistence_data ;
}
AST_RWLIST_HEAD_STATIC ( publish_handlers , ast_sip_publish_handler ) ;
static int publication_hash_fn ( const void * obj , const int flags )
@ -3076,7 +3118,7 @@ static pj_bool_t pubsub_on_rx_subscribe_request(pjsip_rx_data *rdata)
return PJ_TRUE ;
}
sub_tree = create_subscription_tree ( handler , endpoint , rdata , resource , generator , & tree , & dlg_status );
sub_tree = create_subscription_tree ( handler , endpoint , rdata , resource , generator , & tree , & dlg_status , NULL );
if ( ! sub_tree ) {
if ( dlg_status ! = PJ_EEXISTS ) {
pjsip_endpt_respond_stateless ( ast_sip_get_pjsip_endpoint ( ) , rdata , 500 , NULL , NULL , NULL ) ;
@ -4725,6 +4767,39 @@ static int persistence_tag_struct2str(const void *obj, const intptr_t *args, cha
return 0 ;
}
static int persistence_generator_data_str2struct ( const struct aco_option * opt , struct ast_variable * var , void * obj )
{
struct subscription_persistence * persistence = obj ;
struct ast_json_error error ;
/* We tolerate a failure of the JSON to load and instead start fresh, since this field
* originates from the persistence code and not a user .
*/
persistence - > generator_data = ast_json_load_string ( var - > value , & error ) ;
return 0 ;
}
static int persistence_generator_data_struct2str ( const void * obj , const intptr_t * args , char * * buf )
{
const struct subscription_persistence * persistence = obj ;
char * value ;
if ( ! persistence - > generator_data ) {
return 0 ;
}
value = ast_json_dump_string ( persistence - > generator_data ) ;
if ( ! value ) {
return - 1 ;
}
* buf = ast_strdup ( value ) ;
ast_json_free ( value ) ;
return 0 ;
}
static int persistence_expires_str2struct ( const struct aco_option * opt , struct ast_variable * var , void * obj )
{
struct subscription_persistence * persistence = obj ;
@ -5599,6 +5674,8 @@ static int load_module(void)
CHARFLDSET ( struct subscription_persistence , contact_uri ) ) ;
ast_sorcery_object_field_register ( sorcery , " subscription_persistence " , " prune_on_boot " , " no " , OPT_YESNO_T , 1 ,
FLDSET ( struct subscription_persistence , prune_on_boot ) ) ;
ast_sorcery_object_field_register_custom ( sorcery , " subscription_persistence " , " generator_data " , " " ,
persistence_generator_data_str2struct , persistence_generator_data_struct2str , NULL , 0 , 0 ) ;
if ( apply_list_configuration ( sorcery ) ) {
ast_sched_context_destroy ( sched ) ;