@@ -1018,6 +1018,8 @@ static int have_visited(const char *resource, struct resources *visited)
10181018 return 0 ;
10191019}
10201020
1021+ #define NEW_SUBSCRIBE (notifier , endpoint , resource , rdata ) notifier->new_subscribe_with_rdata ? notifier->new_subscribe_with_rdata(endpoint, resource, rdata) : notifier->new_subscribe(endpoint, resource)
1022+
10211023/*!
10221024 * \brief Build child nodes for a given parent.
10231025 *
@@ -1040,7 +1042,7 @@ static int have_visited(const char *resource, struct resources *visited)
10401042 * \param visited The resources that have already been visited.
10411043 */
10421044static void build_node_children (struct ast_sip_endpoint * endpoint , const struct ast_sip_subscription_handler * handler ,
1043- struct resource_list * list , struct tree_node * parent , struct resources * visited )
1045+ struct resource_list * list , struct tree_node * parent , struct resources * visited , pjsip_rx_data * rdata )
10441046{
10451047 int i ;
10461048
@@ -1056,7 +1058,7 @@ static void build_node_children(struct ast_sip_endpoint *endpoint, const struct
10561058
10571059 child_list = retrieve_resource_list (resource , list -> event );
10581060 if (!child_list ) {
1059- int resp = handler -> notifier -> new_subscribe ( endpoint , resource );
1061+ int resp = NEW_SUBSCRIBE ( handler -> notifier , endpoint , resource , rdata );
10601062 if (PJSIP_IS_STATUS_IN_CLASS (resp , 200 )) {
10611063 char display_name [AST_MAX_EXTENSION ] = "" ;
10621064 if (list -> resource_display_name && handler -> notifier -> get_resource_display_name ) {
@@ -1085,7 +1087,7 @@ static void build_node_children(struct ast_sip_endpoint *endpoint, const struct
10851087 ast_debug (1 , "Cannot build children of resource %s due to allocation failure\n" , resource );
10861088 continue ;
10871089 }
1088- build_node_children (endpoint , handler , child_list , current , visited );
1090+ build_node_children (endpoint , handler , child_list , current , visited , rdata );
10891091 if (AST_VECTOR_SIZE (& current -> children ) > 0 ) {
10901092 ast_debug (1 , "List %s had no successful children.\n" , resource );
10911093 if (AST_VECTOR_APPEND (& parent -> children , current )) {
@@ -1158,19 +1160,21 @@ static void resource_tree_destroy(struct resource_tree *tree)
11581160 * \retval 300-699 Failure to subscribe to requested resource.
11591161 */
11601162static int build_resource_tree (struct ast_sip_endpoint * endpoint , const struct ast_sip_subscription_handler * handler ,
1161- const char * resource , struct resource_tree * tree , int has_eventlist_support )
1163+ const char * resource , struct resource_tree * tree , int has_eventlist_support , pjsip_rx_data * rdata )
11621164{
11631165 RAII_VAR (struct resource_list * , list , NULL , ao2_cleanup );
11641166 struct resources visited ;
11651167
1166- if (!has_eventlist_support || !(list = retrieve_resource_list (resource , handler -> event_name ))) {
1168+ int not_eventlist_but_needs_children = !strcmp (handler -> body_type , AST_SIP_DEVICE_FEATURE_SYNC_DATA );
1169+
1170+ if ((!has_eventlist_support && !not_eventlist_but_needs_children ) || !(list = retrieve_resource_list (resource , handler -> event_name ))) {
11671171 ast_debug (2 , "Subscription '%s->%s' is not to a list\n" ,
11681172 ast_sorcery_object_get_id (endpoint ), resource );
11691173 tree -> root = tree_node_alloc (resource , NULL , 0 , NULL );
11701174 if (!tree -> root ) {
11711175 return 500 ;
11721176 }
1173- return handler -> notifier -> new_subscribe ( endpoint , resource );
1177+ return NEW_SUBSCRIBE ( handler -> notifier , endpoint , resource , rdata );
11741178 }
11751179
11761180 ast_debug (2 , "Subscription '%s->%s' is a list\n" ,
@@ -1187,7 +1191,7 @@ static int build_resource_tree(struct ast_sip_endpoint *endpoint, const struct a
11871191
11881192 tree -> notification_batch_interval = list -> notification_batch_interval ;
11891193
1190- build_node_children (endpoint , handler , list , tree -> root , & visited );
1194+ build_node_children (endpoint , handler , list , tree -> root , & visited , rdata );
11911195 AST_VECTOR_FREE (& visited );
11921196
11931197 if (AST_VECTOR_SIZE (& tree -> root -> children ) > 0 ) {
@@ -1380,6 +1384,7 @@ static void shutdown_subscriptions(struct ast_sip_subscription *sub)
13801384 sub -> handler -> subscription_shutdown (sub );
13811385 }
13821386}
1387+
13831388static int subscription_unreference_dialog (void * obj )
13841389{
13851390 struct sip_subscription_tree * sub_tree = obj ;
@@ -1674,7 +1679,7 @@ static int sub_persistence_recreate(void *obj)
16741679
16751680 memset (& tree , 0 , sizeof (tree ));
16761681 resp = build_resource_tree (endpoint , handler , resource , & tree ,
1677- ast_sip_pubsub_has_eventlist_support (rdata ));
1682+ ast_sip_pubsub_has_eventlist_support (rdata ), rdata );
16781683 if (PJSIP_IS_STATUS_IN_CLASS (resp , 200 )) {
16791684 pj_status_t dlg_status ;
16801685
@@ -2454,6 +2459,16 @@ static pjsip_require_hdr *create_require_eventlist(pj_pool_t *pool)
24542459 return require ;
24552460}
24562461
2462+ static void set_state_terminated (struct ast_sip_subscription * sub )
2463+ {
2464+ int i ;
2465+
2466+ sub -> subscription_state = PJSIP_EVSUB_STATE_TERMINATED ;
2467+ for (i = 0 ; i < AST_VECTOR_SIZE (& sub -> children ); ++ i ) {
2468+ set_state_terminated (AST_VECTOR_GET (& sub -> children , i ));
2469+ }
2470+ }
2471+
24572472/*!
24582473 * \brief Send a NOTIFY request to a subscriber
24592474 *
@@ -2491,6 +2506,12 @@ static int send_notify(struct sip_subscription_tree *sub_tree, unsigned int forc
24912506 pjsip_msg_add_hdr (tdata -> msg , (pjsip_hdr * ) require );
24922507 }
24932508
2509+ if (sub_tree -> root -> handler -> notifier -> notify_created ) {
2510+ /* The module for this event wants a callback to the pjsip_tx_data,
2511+ * e.g. so it can add custom headers or do something custom to the response. */
2512+ sub_tree -> root -> handler -> notifier -> notify_created (sub_tree -> root , tdata );
2513+ }
2514+
24942515 if (sip_subscription_send_request (sub_tree , tdata )) {
24952516 /* do not call pjsip_tx_data_dec_ref(tdata). The pjsip_dlg_send_request deletes the message on error */
24962517 return -1 ;
@@ -2954,6 +2975,7 @@ static int generate_initial_notify(struct ast_sip_subscription *sub)
29542975
29552976 notify_data = sub -> handler -> notifier -> get_notify_data (sub );
29562977 if (!notify_data ) {
2978+ ast_debug (3 , "No notify data, not generating any body content\n" );
29572979 return -1 ;
29582980 }
29592981
@@ -3085,7 +3107,7 @@ static pj_bool_t pubsub_on_rx_subscribe_request(pjsip_rx_data *rdata)
30853107
30863108 memset (& tree , 0 , sizeof (tree ));
30873109 resp = build_resource_tree (endpoint , handler , resource , & tree ,
3088- ast_sip_pubsub_has_eventlist_support (rdata ));
3110+ ast_sip_pubsub_has_eventlist_support (rdata ), rdata );
30893111 if (!PJSIP_IS_STATUS_IN_CLASS (resp , 200 )) {
30903112 pjsip_endpt_respond_stateless (ast_sip_get_pjsip_endpoint (), rdata , resp , NULL , NULL , NULL );
30913113 resource_tree_destroy (& tree );
@@ -3095,6 +3117,7 @@ static pj_bool_t pubsub_on_rx_subscribe_request(pjsip_rx_data *rdata)
30953117 sub_tree = create_subscription_tree (handler , endpoint , rdata , resource , generator , & tree , & dlg_status , NULL );
30963118 if (!sub_tree ) {
30973119 if (dlg_status != PJ_EEXISTS ) {
3120+ ast_debug (3 , "No dialog exists, rejecting\n" );
30983121 pjsip_endpt_respond_stateless (ast_sip_get_pjsip_endpoint (), rdata , 500 , NULL , NULL , NULL );
30993122 }
31003123 } else {
@@ -3331,6 +3354,7 @@ static struct ast_sip_publication *publish_request_initial(struct ast_sip_endpoi
33313354 publication -> handler = handler ;
33323355 if (publication -> handler -> publication_state_change (publication , rdata -> msg_info .msg -> body ,
33333356 AST_SIP_PUBLISH_STATE_INITIALIZED )) {
3357+ ast_debug (3 , "Publication state change failed\n" );
33343358 pjsip_endpt_respond_stateless (ast_sip_get_pjsip_endpoint (), rdata , 500 , NULL , NULL , NULL );
33353359 ao2_cleanup (publication );
33363360 return NULL ;
@@ -3760,16 +3784,6 @@ static pj_bool_t pubsub_on_rx_request(pjsip_rx_data *rdata)
37603784 return PJ_FALSE ;
37613785}
37623786
3763- static void set_state_terminated (struct ast_sip_subscription * sub )
3764- {
3765- int i ;
3766-
3767- sub -> subscription_state = PJSIP_EVSUB_STATE_TERMINATED ;
3768- for (i = 0 ; i < AST_VECTOR_SIZE (& sub -> children ); ++ i ) {
3769- set_state_terminated (AST_VECTOR_GET (& sub -> children , i ));
3770- }
3771- }
3772-
37733787/*!
37743788 * \brief Callback sequence for subscription terminate:
37753789 *
@@ -3852,7 +3866,8 @@ static void set_state_terminated(struct ast_sip_subscription *sub)
38523866
38533867
38543868/* The code in this function was previously in pubsub_on_evsub_state. */
3855- static void clean_sub_tree (pjsip_evsub * evsub ){
3869+ static void clean_sub_tree (pjsip_evsub * evsub )
3870+ {
38563871
38573872 struct sip_subscription_tree * sub_tree ;
38583873 sub_tree = pjsip_evsub_get_mod_data (evsub , pubsub_module .id );
@@ -3917,7 +3932,6 @@ static void pubsub_on_evsub_state(pjsip_evsub *evsub, pjsip_event *event)
39173932 return ;
39183933 }
39193934
3920-
39213935 /* It's easier to write this as what we WANT to process, then negate it. */
39223936 if (!(sub_tree -> state == SIP_SUB_TREE_TERMINATE_IN_PROGRESS
39233937 || (event -> type == PJSIP_EVENT_TSX_STATE && sub_tree -> state == SIP_SUB_TREE_NORMAL )
@@ -3932,9 +3946,8 @@ static void pubsub_on_evsub_state(pjsip_evsub *evsub, pjsip_event *event)
39323946 This was previously handled by pubsub_on_rx_refresh setting:
39333947 'sub_tree->state = SIP_SUB_TREE_TERMINATE_PENDING' */
39343948 if (event -> body .tsx_state .type == PJSIP_EVENT_RX_MSG &&
3935- !pjsip_method_cmp (& event -> body .tsx_state .tsx -> method , & pjsip_subscribe_method ) &&
3936- pjsip_evsub_get_expires (evsub ) == 0 ) {
3937-
3949+ !pjsip_method_cmp (& event -> body .tsx_state .tsx -> method , & pjsip_subscribe_method ) &&
3950+ pjsip_evsub_get_expires (evsub ) == 0 ) {
39383951 ast_debug (3 , "Subscription ending, do nothing.\n" );
39393952 return ;
39403953 }
@@ -4063,6 +4076,7 @@ static void pubsub_on_rx_refresh(pjsip_evsub *evsub, pjsip_rx_data *rdata,
40634076 int * p_st_code , pj_str_t * * p_st_text , pjsip_hdr * res_hdr , pjsip_msg_body * * p_body )
40644077{
40654078 struct sip_subscription_tree * sub_tree ;
4079+ RAII_VAR (struct ast_sip_endpoint * , endpoint , NULL , ao2_cleanup );
40664080
40674081 sub_tree = pjsip_evsub_get_mod_data (evsub , pubsub_module .id );
40684082 ast_debug (3 , "evsub %p sub_tree %p sub_tree state %s\n" , evsub , sub_tree ,
@@ -4090,27 +4104,33 @@ static void pubsub_on_rx_refresh(pjsip_evsub *evsub, pjsip_rx_data *rdata,
40904104 sub_tree -> state = SIP_SUB_TREE_TERMINATE_PENDING ;
40914105 }
40924106
4107+ endpoint = ast_pjsip_rdata_get_endpoint (rdata );
4108+
4109+ /* If the handler wants a callback on refresh, then do it (some protocols require this). */
4110+ if (sub_tree -> state == SIP_SUB_TREE_NORMAL && sub_tree -> root -> handler -> notifier -> refresh_subscribe ) {
4111+ if (!sub_tree -> root -> handler -> notifier -> refresh_subscribe (sub_tree -> root , rdata )) {
4112+ return ; /* If the callback handled it, we're done. */
4113+ }
4114+ }
4115+
40934116 if (sub_tree -> state == SIP_SUB_TREE_NORMAL && sub_tree -> is_list ) {
40944117 /* update RLS */
40954118 const char * resource = sub_tree -> root -> resource ;
40964119 struct ast_sip_subscription * old_root = sub_tree -> root ;
40974120 struct ast_sip_subscription * new_root = NULL ;
4098- RAII_VAR (struct ast_sip_endpoint * , endpoint , NULL , ao2_cleanup );
4099- struct ast_sip_subscription_handler * handler = NULL ;
4121+
41004122 struct ast_sip_pubsub_body_generator * generator = NULL ;
41014123
4102- if ((endpoint = ast_pjsip_rdata_get_endpoint (rdata ))
4103- && (handler = subscription_get_handler_from_rdata (rdata , ast_sorcery_object_get_id (endpoint )))
4104- && (generator = subscription_get_generator_from_rdata (rdata , handler ))) {
4124+ if (endpoint && (generator = subscription_get_generator_from_rdata (rdata , sub_tree -> root -> handler ))) {
41054125
41064126 struct resource_tree tree ;
41074127 int resp ;
41084128
41094129 memset (& tree , 0 , sizeof (tree ));
4110- resp = build_resource_tree (endpoint , handler , resource , & tree ,
4111- ast_sip_pubsub_has_eventlist_support (rdata ));
4130+ resp = build_resource_tree (endpoint , sub_tree -> root -> handler , resource , & tree ,
4131+ ast_sip_pubsub_has_eventlist_support (rdata ), rdata );
41124132 if (PJSIP_IS_STATUS_IN_CLASS (resp , 200 )) {
4113- new_root = create_virtual_subscriptions (handler , resource , generator , sub_tree , tree .root );
4133+ new_root = create_virtual_subscriptions (sub_tree -> root -> handler , resource , generator , sub_tree , tree .root );
41144134 if (new_root ) {
41154135 if (cmp_subscription_childrens (old_root , new_root )) {
41164136 ast_debug (1 , "RLS '%s->%s' was modified, regenerate it\n" , ast_sorcery_object_get_id (endpoint ), old_root -> resource );
@@ -5335,7 +5355,7 @@ AST_TEST_DEFINE(resource_tree)
53355355 }
53365356
53375357 tree = ast_calloc (1 , sizeof (* tree ));
5338- resp = build_resource_tree (NULL , & test_handler , "foo" , tree , 1 );
5358+ resp = build_resource_tree (NULL , & test_handler , "foo" , tree , 1 , NULL );
53395359 if (resp != 200 ) {
53405360 ast_test_status_update (test , "Unexpected response %d when building resource tree\n" , resp );
53415361 return AST_TEST_FAIL ;
@@ -5405,7 +5425,7 @@ AST_TEST_DEFINE(complex_resource_tree)
54055425 }
54065426
54075427 tree = ast_calloc (1 , sizeof (* tree ));
5408- resp = build_resource_tree (NULL , & test_handler , "foo" , tree , 1 );
5428+ resp = build_resource_tree (NULL , & test_handler , "foo" , tree , 1 , NULL );
54095429 if (resp != 200 ) {
54105430 ast_test_status_update (test , "Unexpected response %d when building resource tree\n" , resp );
54115431 return AST_TEST_FAIL ;
@@ -5466,7 +5486,7 @@ AST_TEST_DEFINE(bad_resource)
54665486 }
54675487
54685488 tree = ast_calloc (1 , sizeof (* tree ));
5469- resp = build_resource_tree (NULL , & test_handler , "foo" , tree , 1 );
5489+ resp = build_resource_tree (NULL , & test_handler , "foo" , tree , 1 , NULL );
54705490 if (resp != 200 ) {
54715491 ast_test_status_update (test , "Unexpected response %d when building resource tree\n" , resp );
54725492 return AST_TEST_FAIL ;
@@ -5535,7 +5555,7 @@ AST_TEST_DEFINE(bad_branch)
55355555 }
55365556
55375557 tree = ast_calloc (1 , sizeof (* tree ));
5538- resp = build_resource_tree (NULL , & test_handler , "foo" , tree , 1 );
5558+ resp = build_resource_tree (NULL , & test_handler , "foo" , tree , 1 , NULL );
55395559 if (resp != 200 ) {
55405560 ast_test_status_update (test , "Unexpected response %d when building resource tree\n" , resp );
55415561 return AST_TEST_FAIL ;
@@ -5608,7 +5628,7 @@ AST_TEST_DEFINE(duplicate_resource)
56085628 }
56095629
56105630 tree = ast_calloc (1 , sizeof (* tree ));
5611- resp = build_resource_tree (NULL , & test_handler , "foo" , tree , 1 );
5631+ resp = build_resource_tree (NULL , & test_handler , "foo" , tree , 1 , NULL );
56125632 if (resp != 200 ) {
56135633 ast_test_status_update (test , "Unexpected response %d when building resource tree\n" , resp );
56145634 return AST_TEST_FAIL ;
@@ -5680,7 +5700,7 @@ AST_TEST_DEFINE(loop)
56805700 }
56815701
56825702 tree = ast_calloc (1 , sizeof (* tree ));
5683- resp = build_resource_tree (NULL , & test_handler , "herp" , tree , 1 );
5703+ resp = build_resource_tree (NULL , & test_handler , "herp" , tree , 1 , NULL );
56845704 if (resp == 200 ) {
56855705 ast_test_status_update (test , "Unexpected response %d when building resource tree\n" , resp );
56865706 return AST_TEST_FAIL ;
@@ -5727,7 +5747,7 @@ AST_TEST_DEFINE(bad_event)
57275747 /* Since the test_handler is for event "test", this should not build a list, but
57285748 * instead result in a single resource being created, called "foo"
57295749 */
5730- resp = build_resource_tree (NULL , & test_handler , "foo" , tree , 1 );
5750+ resp = build_resource_tree (NULL , & test_handler , "foo" , tree , 1 , NULL );
57315751 if (resp != 200 ) {
57325752 ast_test_status_update (test , "Unexpected response %d when building resource tree\n" , resp );
57335753 return AST_TEST_FAIL ;
0 commit comments