@@ -1018,6 +1018,8 @@ static int have_visited(const char *resource, struct resources *visited)
1018
1018
return 0 ;
1019
1019
}
1020
1020
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
+
1021
1023
/*!
1022
1024
* \brief Build child nodes for a given parent.
1023
1025
*
@@ -1040,7 +1042,7 @@ static int have_visited(const char *resource, struct resources *visited)
1040
1042
* \param visited The resources that have already been visited.
1041
1043
*/
1042
1044
static 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 )
1044
1046
{
1045
1047
int i ;
1046
1048
@@ -1056,7 +1058,7 @@ static void build_node_children(struct ast_sip_endpoint *endpoint, const struct
1056
1058
1057
1059
child_list = retrieve_resource_list (resource , list -> event );
1058
1060
if (!child_list ) {
1059
- int resp = handler -> notifier -> new_subscribe ( endpoint , resource );
1061
+ int resp = NEW_SUBSCRIBE ( handler -> notifier , endpoint , resource , rdata );
1060
1062
if (PJSIP_IS_STATUS_IN_CLASS (resp , 200 )) {
1061
1063
char display_name [AST_MAX_EXTENSION ] = "" ;
1062
1064
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
1085
1087
ast_debug (1 , "Cannot build children of resource %s due to allocation failure\n" , resource );
1086
1088
continue ;
1087
1089
}
1088
- build_node_children (endpoint , handler , child_list , current , visited );
1090
+ build_node_children (endpoint , handler , child_list , current , visited , rdata );
1089
1091
if (AST_VECTOR_SIZE (& current -> children ) > 0 ) {
1090
1092
ast_debug (1 , "List %s had no successful children.\n" , resource );
1091
1093
if (AST_VECTOR_APPEND (& parent -> children , current )) {
@@ -1158,19 +1160,21 @@ static void resource_tree_destroy(struct resource_tree *tree)
1158
1160
* \retval 300-699 Failure to subscribe to requested resource.
1159
1161
*/
1160
1162
static 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 )
1162
1164
{
1163
1165
RAII_VAR (struct resource_list * , list , NULL , ao2_cleanup );
1164
1166
struct resources visited ;
1165
1167
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 ))) {
1167
1171
ast_debug (2 , "Subscription '%s->%s' is not to a list\n" ,
1168
1172
ast_sorcery_object_get_id (endpoint ), resource );
1169
1173
tree -> root = tree_node_alloc (resource , NULL , 0 , NULL );
1170
1174
if (!tree -> root ) {
1171
1175
return 500 ;
1172
1176
}
1173
- return handler -> notifier -> new_subscribe ( endpoint , resource );
1177
+ return NEW_SUBSCRIBE ( handler -> notifier , endpoint , resource , rdata );
1174
1178
}
1175
1179
1176
1180
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
1187
1191
1188
1192
tree -> notification_batch_interval = list -> notification_batch_interval ;
1189
1193
1190
- build_node_children (endpoint , handler , list , tree -> root , & visited );
1194
+ build_node_children (endpoint , handler , list , tree -> root , & visited , rdata );
1191
1195
AST_VECTOR_FREE (& visited );
1192
1196
1193
1197
if (AST_VECTOR_SIZE (& tree -> root -> children ) > 0 ) {
@@ -1380,6 +1384,7 @@ static void shutdown_subscriptions(struct ast_sip_subscription *sub)
1380
1384
sub -> handler -> subscription_shutdown (sub );
1381
1385
}
1382
1386
}
1387
+
1383
1388
static int subscription_unreference_dialog (void * obj )
1384
1389
{
1385
1390
struct sip_subscription_tree * sub_tree = obj ;
@@ -1674,7 +1679,7 @@ static int sub_persistence_recreate(void *obj)
1674
1679
1675
1680
memset (& tree , 0 , sizeof (tree ));
1676
1681
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 );
1678
1683
if (PJSIP_IS_STATUS_IN_CLASS (resp , 200 )) {
1679
1684
pj_status_t dlg_status ;
1680
1685
@@ -2454,6 +2459,16 @@ static pjsip_require_hdr *create_require_eventlist(pj_pool_t *pool)
2454
2459
return require ;
2455
2460
}
2456
2461
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
+
2457
2472
/*!
2458
2473
* \brief Send a NOTIFY request to a subscriber
2459
2474
*
@@ -2491,6 +2506,12 @@ static int send_notify(struct sip_subscription_tree *sub_tree, unsigned int forc
2491
2506
pjsip_msg_add_hdr (tdata -> msg , (pjsip_hdr * ) require );
2492
2507
}
2493
2508
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
+
2494
2515
if (sip_subscription_send_request (sub_tree , tdata )) {
2495
2516
/* do not call pjsip_tx_data_dec_ref(tdata). The pjsip_dlg_send_request deletes the message on error */
2496
2517
return -1 ;
@@ -2954,6 +2975,7 @@ static int generate_initial_notify(struct ast_sip_subscription *sub)
2954
2975
2955
2976
notify_data = sub -> handler -> notifier -> get_notify_data (sub );
2956
2977
if (!notify_data ) {
2978
+ ast_debug (3 , "No notify data, not generating any body content\n" );
2957
2979
return -1 ;
2958
2980
}
2959
2981
@@ -3085,7 +3107,7 @@ static pj_bool_t pubsub_on_rx_subscribe_request(pjsip_rx_data *rdata)
3085
3107
3086
3108
memset (& tree , 0 , sizeof (tree ));
3087
3109
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 );
3089
3111
if (!PJSIP_IS_STATUS_IN_CLASS (resp , 200 )) {
3090
3112
pjsip_endpt_respond_stateless (ast_sip_get_pjsip_endpoint (), rdata , resp , NULL , NULL , NULL );
3091
3113
resource_tree_destroy (& tree );
@@ -3095,6 +3117,7 @@ static pj_bool_t pubsub_on_rx_subscribe_request(pjsip_rx_data *rdata)
3095
3117
sub_tree = create_subscription_tree (handler , endpoint , rdata , resource , generator , & tree , & dlg_status , NULL );
3096
3118
if (!sub_tree ) {
3097
3119
if (dlg_status != PJ_EEXISTS ) {
3120
+ ast_debug (3 , "No dialog exists, rejecting\n" );
3098
3121
pjsip_endpt_respond_stateless (ast_sip_get_pjsip_endpoint (), rdata , 500 , NULL , NULL , NULL );
3099
3122
}
3100
3123
} else {
@@ -3331,6 +3354,7 @@ static struct ast_sip_publication *publish_request_initial(struct ast_sip_endpoi
3331
3354
publication -> handler = handler ;
3332
3355
if (publication -> handler -> publication_state_change (publication , rdata -> msg_info .msg -> body ,
3333
3356
AST_SIP_PUBLISH_STATE_INITIALIZED )) {
3357
+ ast_debug (3 , "Publication state change failed\n" );
3334
3358
pjsip_endpt_respond_stateless (ast_sip_get_pjsip_endpoint (), rdata , 500 , NULL , NULL , NULL );
3335
3359
ao2_cleanup (publication );
3336
3360
return NULL ;
@@ -3760,16 +3784,6 @@ static pj_bool_t pubsub_on_rx_request(pjsip_rx_data *rdata)
3760
3784
return PJ_FALSE ;
3761
3785
}
3762
3786
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
-
3773
3787
/*!
3774
3788
* \brief Callback sequence for subscription terminate:
3775
3789
*
@@ -3852,7 +3866,8 @@ static void set_state_terminated(struct ast_sip_subscription *sub)
3852
3866
3853
3867
3854
3868
/* 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
+ {
3856
3871
3857
3872
struct sip_subscription_tree * sub_tree ;
3858
3873
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)
3917
3932
return ;
3918
3933
}
3919
3934
3920
-
3921
3935
/* It's easier to write this as what we WANT to process, then negate it. */
3922
3936
if (!(sub_tree -> state == SIP_SUB_TREE_TERMINATE_IN_PROGRESS
3923
3937
|| (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)
3932
3946
This was previously handled by pubsub_on_rx_refresh setting:
3933
3947
'sub_tree->state = SIP_SUB_TREE_TERMINATE_PENDING' */
3934
3948
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 ) {
3938
3951
ast_debug (3 , "Subscription ending, do nothing.\n" );
3939
3952
return ;
3940
3953
}
@@ -4063,6 +4076,7 @@ static void pubsub_on_rx_refresh(pjsip_evsub *evsub, pjsip_rx_data *rdata,
4063
4076
int * p_st_code , pj_str_t * * p_st_text , pjsip_hdr * res_hdr , pjsip_msg_body * * p_body )
4064
4077
{
4065
4078
struct sip_subscription_tree * sub_tree ;
4079
+ RAII_VAR (struct ast_sip_endpoint * , endpoint , NULL , ao2_cleanup );
4066
4080
4067
4081
sub_tree = pjsip_evsub_get_mod_data (evsub , pubsub_module .id );
4068
4082
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,
4090
4104
sub_tree -> state = SIP_SUB_TREE_TERMINATE_PENDING ;
4091
4105
}
4092
4106
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
+
4093
4116
if (sub_tree -> state == SIP_SUB_TREE_NORMAL && sub_tree -> is_list ) {
4094
4117
/* update RLS */
4095
4118
const char * resource = sub_tree -> root -> resource ;
4096
4119
struct ast_sip_subscription * old_root = sub_tree -> root ;
4097
4120
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
+
4100
4122
struct ast_sip_pubsub_body_generator * generator = NULL ;
4101
4123
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 ))) {
4105
4125
4106
4126
struct resource_tree tree ;
4107
4127
int resp ;
4108
4128
4109
4129
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 );
4112
4132
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 );
4114
4134
if (new_root ) {
4115
4135
if (cmp_subscription_childrens (old_root , new_root )) {
4116
4136
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)
5335
5355
}
5336
5356
5337
5357
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 );
5339
5359
if (resp != 200 ) {
5340
5360
ast_test_status_update (test , "Unexpected response %d when building resource tree\n" , resp );
5341
5361
return AST_TEST_FAIL ;
@@ -5405,7 +5425,7 @@ AST_TEST_DEFINE(complex_resource_tree)
5405
5425
}
5406
5426
5407
5427
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 );
5409
5429
if (resp != 200 ) {
5410
5430
ast_test_status_update (test , "Unexpected response %d when building resource tree\n" , resp );
5411
5431
return AST_TEST_FAIL ;
@@ -5466,7 +5486,7 @@ AST_TEST_DEFINE(bad_resource)
5466
5486
}
5467
5487
5468
5488
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 );
5470
5490
if (resp != 200 ) {
5471
5491
ast_test_status_update (test , "Unexpected response %d when building resource tree\n" , resp );
5472
5492
return AST_TEST_FAIL ;
@@ -5535,7 +5555,7 @@ AST_TEST_DEFINE(bad_branch)
5535
5555
}
5536
5556
5537
5557
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 );
5539
5559
if (resp != 200 ) {
5540
5560
ast_test_status_update (test , "Unexpected response %d when building resource tree\n" , resp );
5541
5561
return AST_TEST_FAIL ;
@@ -5608,7 +5628,7 @@ AST_TEST_DEFINE(duplicate_resource)
5608
5628
}
5609
5629
5610
5630
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 );
5612
5632
if (resp != 200 ) {
5613
5633
ast_test_status_update (test , "Unexpected response %d when building resource tree\n" , resp );
5614
5634
return AST_TEST_FAIL ;
@@ -5680,7 +5700,7 @@ AST_TEST_DEFINE(loop)
5680
5700
}
5681
5701
5682
5702
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 );
5684
5704
if (resp == 200 ) {
5685
5705
ast_test_status_update (test , "Unexpected response %d when building resource tree\n" , resp );
5686
5706
return AST_TEST_FAIL ;
@@ -5727,7 +5747,7 @@ AST_TEST_DEFINE(bad_event)
5727
5747
/* Since the test_handler is for event "test", this should not build a list, but
5728
5748
* instead result in a single resource being created, called "foo"
5729
5749
*/
5730
- resp = build_resource_tree (NULL , & test_handler , "foo" , tree , 1 );
5750
+ resp = build_resource_tree (NULL , & test_handler , "foo" , tree , 1 , NULL );
5731
5751
if (resp != 200 ) {
5732
5752
ast_test_status_update (test , "Unexpected response %d when building resource tree\n" , resp );
5733
5753
return AST_TEST_FAIL ;
0 commit comments