<p>N A has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/20031">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">res_pjsip_pubsub: Add new pubsub module capabilities.<br><br>The existing res_pjsip_pubsub APIs are somewhat limited in<br>what they can do. This adds a few API extensions that make<br>it possible for PJSIP pubsub modules to implement richer<br>features than is currently possible.<br><br>* Allow pubsub modules to get a handle to pjsip_rx_data on subscription<br>* Allow pubsub modules to run a callback when a subscription is renewed<br>* Allow pubsub modules to run a callback for outgoing NOTIFYs, with<br>  a handle to the tdata, so that modules can append their own headers<br>  to the NOTIFYs<br><br>This change does not add any features directly, but makes possible<br>several new features that will be added in future changes.<br><br>ASTERISK-30485 #close<br><br>Master-Only: True<br>Change-Id: I5c54d32223eedab7460ca28616ed50ba4ce1341f<br>---<br>M include/asterisk/res_pjsip_pubsub.h<br>M res/res_pjsip_pubsub.c<br>2 files changed, 139 insertions(+), 36 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/31/20031/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/asterisk/res_pjsip_pubsub.h b/include/asterisk/res_pjsip_pubsub.h</span><br><span>index aca1141..ac4bda8 100644</span><br><span>--- a/include/asterisk/res_pjsip_pubsub.h</span><br><span>+++ b/include/asterisk/res_pjsip_pubsub.h</span><br><span>@@ -269,6 +269,18 @@</span><br><span>   */</span><br><span>  int (*new_subscribe)(struct ast_sip_endpoint *endpoint, const char *resource);</span><br><span>       /*!</span><br><span style="color: hsl(120, 100%, 40%);">+    * \brief Same as new_subscribe, but also pass a handle to the pjsip_rx_data</span><br><span style="color: hsl(120, 100%, 40%);">+   *</span><br><span style="color: hsl(120, 100%, 40%);">+     * \note If this callback exists, it will be executed, otherwise new_subscribe will be.</span><br><span style="color: hsl(120, 100%, 40%);">+        *       Only use this if you need the rdata. Otherwise, use new_subscribe.</span><br><span style="color: hsl(120, 100%, 40%);">+    *</span><br><span style="color: hsl(120, 100%, 40%);">+     * \param endpoint The endpoint from which we received the SUBSCRIBE</span><br><span style="color: hsl(120, 100%, 40%);">+   * \param resource The name of the resource to which the subscription is being made</span><br><span style="color: hsl(120, 100%, 40%);">+    * \param rdata The pjsip_rx_data for incoming subscription</span><br><span style="color: hsl(120, 100%, 40%);">+    * \return The response code to send to the SUBSCRIBE.</span><br><span style="color: hsl(120, 100%, 40%);">+         */</span><br><span style="color: hsl(120, 100%, 40%);">+   int (*new_subscribe_with_rdata)(struct ast_sip_endpoint *endpoint, const char *resource, pjsip_rx_data *rdata);</span><br><span style="color: hsl(120, 100%, 40%);">+       /*!</span><br><span>   * \brief Called when an inbound subscription has been accepted.</span><br><span>      *</span><br><span>    * This is a prime opportunity for notifiers to add any notifier-specific</span><br><span>@@ -283,6 +295,25 @@</span><br><span>      */</span><br><span>  int (*subscription_established)(struct ast_sip_subscription *sub);</span><br><span>   /*!</span><br><span style="color: hsl(120, 100%, 40%);">+    * \brief Called when a SUBSCRIBE arrives for an already active subscription.</span><br><span style="color: hsl(120, 100%, 40%);">+  *</span><br><span style="color: hsl(120, 100%, 40%);">+     * \param sub The existing subscription</span><br><span style="color: hsl(120, 100%, 40%);">+        * \retval 0 Success</span><br><span style="color: hsl(120, 100%, 40%);">+   * \retval -1 Failure</span><br><span style="color: hsl(120, 100%, 40%);">+  */</span><br><span style="color: hsl(120, 100%, 40%);">+   int (*refresh_subscribe)(struct ast_sip_subscription *sub, pjsip_rx_data *rdata);</span><br><span style="color: hsl(120, 100%, 40%);">+     /*!</span><br><span style="color: hsl(120, 100%, 40%);">+    * \brief Optional callback to execute before sending outgoing NOTIFY responses.</span><br><span style="color: hsl(120, 100%, 40%);">+       *        Because res_pjsip_pubsub creates the tdata internally, this allows modules</span><br><span style="color: hsl(120, 100%, 40%);">+   *        to access the tdata if needed, e.g. to add custom headers.</span><br><span style="color: hsl(120, 100%, 40%);">+   *</span><br><span style="color: hsl(120, 100%, 40%);">+     * \param sub The existing subscription</span><br><span style="color: hsl(120, 100%, 40%);">+        * \param tdata The pjsip_tx_data to use for the outgoing NOTIFY</span><br><span style="color: hsl(120, 100%, 40%);">+       * \retval 0 Success</span><br><span style="color: hsl(120, 100%, 40%);">+   * \retval -1 Failure</span><br><span style="color: hsl(120, 100%, 40%);">+  */</span><br><span style="color: hsl(120, 100%, 40%);">+   int (*tdata_callback)(struct ast_sip_subscription *sub, pjsip_tx_data *tdata);</span><br><span style="color: hsl(120, 100%, 40%);">+        /*!</span><br><span>   * \brief Supply data needed to create a NOTIFY body.</span><br><span>         *</span><br><span>    * The returned data must be an ao2 object. The caller of this function</span><br><span>diff --git a/res/res_pjsip_pubsub.c b/res/res_pjsip_pubsub.c</span><br><span>index 6ddb2fd..c8923d6 100644</span><br><span>--- a/res/res_pjsip_pubsub.c</span><br><span>+++ b/res/res_pjsip_pubsub.c</span><br><span>@@ -807,6 +807,30 @@</span><br><span>  return handler;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! \brief Retrieve a handler using the Event header of a tdata message */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_sip_subscription_handler *subscription_get_handler_from_tdata(pjsip_tx_data *tdata, const char *endpoint)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  pjsip_event_hdr *event_header;</span><br><span style="color: hsl(120, 100%, 40%);">+        char event[32];</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ast_sip_subscription_handler *handler;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       event_header = pjsip_msg_find_hdr_by_name(tdata->msg, &str_event_name, tdata->msg->hdr.next);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!event_header) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_log(LOG_WARNING, "Incoming SUBSCRIBE request from %s with no Event header\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                   endpoint ? endpoint : "Unknown");</span><br><span style="color: hsl(120, 100%, 40%);">+           return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_copy_pj_str(event, &event_header->event_type, sizeof(event));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    handler = find_sub_handler_for_event_name(event);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!handler) {</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_log(LOG_WARNING, "No registered subscribe handler for event %s from %s\n", event,</span><br><span style="color: hsl(120, 100%, 40%);">+                       endpoint ? endpoint : "Unknown");</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return handler;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*!</span><br><span>  * \brief Accept headers that are exceptions to the rule</span><br><span>  *</span><br><span>@@ -1018,6 +1042,8 @@</span><br><span>        return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#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)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*!</span><br><span>  * \brief Build child nodes for a given parent.</span><br><span>  *</span><br><span>@@ -1040,7 +1066,7 @@</span><br><span>  * \param visited The resources that have already been visited.</span><br><span>  */</span><br><span> static void build_node_children(struct ast_sip_endpoint *endpoint, const struct ast_sip_subscription_handler *handler,</span><br><span style="color: hsl(0, 100%, 40%);">-          struct resource_list *list, struct tree_node *parent, struct resources *visited)</span><br><span style="color: hsl(120, 100%, 40%);">+              struct resource_list *list, struct tree_node *parent, struct resources *visited, pjsip_rx_data *rdata)</span><br><span> {</span><br><span>  int i;</span><br><span> </span><br><span>@@ -1056,7 +1082,7 @@</span><br><span> </span><br><span>               child_list = retrieve_resource_list(resource, list->event);</span><br><span>               if (!child_list) {</span><br><span style="color: hsl(0, 100%, 40%);">-                      int resp = handler->notifier->new_subscribe(endpoint, resource);</span><br><span style="color: hsl(120, 100%, 40%);">+                        int resp = NEW_SUBSCRIBE(handler->notifier, endpoint, resource, rdata);</span><br><span>                   if (PJSIP_IS_STATUS_IN_CLASS(resp, 200)) {</span><br><span>                           char display_name[AST_MAX_EXTENSION] = "";</span><br><span>                                 if (list->resource_display_name && handler->notifier->get_resource_display_name) {</span><br><span>@@ -1085,7 +1111,7 @@</span><br><span>                          ast_debug(1, "Cannot build children of resource %s due to allocation failure\n", resource);</span><br><span>                                continue;</span><br><span>                    }</span><br><span style="color: hsl(0, 100%, 40%);">-                       build_node_children(endpoint, handler, child_list, current, visited);</span><br><span style="color: hsl(120, 100%, 40%);">+                 build_node_children(endpoint, handler, child_list, current, visited, rdata);</span><br><span>                         if (AST_VECTOR_SIZE(&current->children) > 0) {</span><br><span>                             ast_debug(1, "List %s had no successful children.\n", resource);</span><br><span>                           if (AST_VECTOR_APPEND(&parent->children, current)) {</span><br><span>@@ -1158,7 +1184,7 @@</span><br><span>  * \retval 300-699 Failure to subscribe to requested resource.</span><br><span>  */</span><br><span> static int build_resource_tree(struct ast_sip_endpoint *endpoint, const struct ast_sip_subscription_handler *handler,</span><br><span style="color: hsl(0, 100%, 40%);">-           const char *resource, struct resource_tree *tree, int has_eventlist_support)</span><br><span style="color: hsl(120, 100%, 40%);">+          const char *resource, struct resource_tree *tree, int has_eventlist_support, pjsip_rx_data *rdata)</span><br><span> {</span><br><span>      RAII_VAR(struct resource_list *, list, NULL, ao2_cleanup);</span><br><span>   struct resources visited;</span><br><span>@@ -1170,7 +1196,7 @@</span><br><span>            if (!tree->root) {</span><br><span>                        return 500;</span><br><span>          }</span><br><span style="color: hsl(0, 100%, 40%);">-               return handler->notifier->new_subscribe(endpoint, resource);</span><br><span style="color: hsl(120, 100%, 40%);">+            return NEW_SUBSCRIBE(handler->notifier, endpoint, resource, rdata);</span><br><span>       }</span><br><span> </span><br><span>        ast_debug(2, "Subscription '%s->%s' is a list\n",</span><br><span>@@ -1187,7 +1213,7 @@</span><br><span> </span><br><span>   tree->notification_batch_interval = list->notification_batch_interval;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        build_node_children(endpoint, handler, list, tree->root, &visited);</span><br><span style="color: hsl(120, 100%, 40%);">+    build_node_children(endpoint, handler, list, tree->root, &visited, rdata);</span><br><span>    AST_VECTOR_FREE(&visited);</span><br><span> </span><br><span>   if (AST_VECTOR_SIZE(&tree->root->children) > 0) {</span><br><span>@@ -1380,6 +1406,7 @@</span><br><span>               sub->handler->subscription_shutdown(sub);</span><br><span>      }</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static int subscription_unreference_dialog(void *obj)</span><br><span> {</span><br><span>       struct sip_subscription_tree *sub_tree = obj;</span><br><span>@@ -1674,7 +1701,7 @@</span><br><span> </span><br><span>    memset(&tree, 0, sizeof(tree));</span><br><span>  resp = build_resource_tree(endpoint, handler, resource, &tree,</span><br><span style="color: hsl(0, 100%, 40%);">-              ast_sip_pubsub_has_eventlist_support(rdata));</span><br><span style="color: hsl(120, 100%, 40%);">+         ast_sip_pubsub_has_eventlist_support(rdata), rdata);</span><br><span>         if (PJSIP_IS_STATUS_IN_CLASS(resp, 200)) {</span><br><span>           pj_status_t dlg_status;</span><br><span> </span><br><span>@@ -2454,6 +2481,16 @@</span><br><span>         return require;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static void set_state_terminated(struct ast_sip_subscription *sub)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      sub->subscription_state = PJSIP_EVSUB_STATE_TERMINATED;</span><br><span style="color: hsl(120, 100%, 40%);">+    for (i = 0; i < AST_VECTOR_SIZE(&sub->children); ++i) {</span><br><span style="color: hsl(120, 100%, 40%);">+             set_state_terminated(AST_VECTOR_GET(&sub->children, i));</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*!</span><br><span>  * \brief Send a NOTIFY request to a subscriber</span><br><span>  *</span><br><span>@@ -2468,6 +2505,7 @@</span><br><span> {</span><br><span>  pjsip_evsub *evsub = sub_tree->evsub;</span><br><span>     pjsip_tx_data *tdata;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_sip_subscription_handler *handler;</span><br><span> </span><br><span>    if (ast_shutdown_final()</span><br><span>             && sub_tree->root->subscription_state == PJSIP_EVSUB_STATE_TERMINATED</span><br><span>@@ -2491,6 +2529,13 @@</span><br><span>                 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) require);</span><br><span>     }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ handler = subscription_get_handler_from_tdata(tdata, sub_tree->persistence->endpoint);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (handler->notifier->tdata_callback) {</span><br><span style="color: hsl(120, 100%, 40%);">+                /* The module for this event wants a callback to the pjsip_tx_data,</span><br><span style="color: hsl(120, 100%, 40%);">+            * e.g. so it can add custom headers or do something custom to the response. */</span><br><span style="color: hsl(120, 100%, 40%);">+               handler->notifier->tdata_callback(sub_tree->root, tdata);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  if (sip_subscription_send_request(sub_tree, tdata)) {</span><br><span>                /* do not call pjsip_tx_data_dec_ref(tdata). The pjsip_dlg_send_request deletes the message on error */</span><br><span>              return -1;</span><br><span>@@ -2954,6 +2999,7 @@</span><br><span> </span><br><span>       notify_data = sub->handler->notifier->get_notify_data(sub);</span><br><span>         if (!notify_data) {</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_debug(3, "No notify data, terminating\n");</span><br><span>             return -1;</span><br><span>   }</span><br><span> </span><br><span>@@ -3085,7 +3131,7 @@</span><br><span> </span><br><span>    memset(&tree, 0, sizeof(tree));</span><br><span>  resp = build_resource_tree(endpoint, handler, resource, &tree,</span><br><span style="color: hsl(0, 100%, 40%);">-              ast_sip_pubsub_has_eventlist_support(rdata));</span><br><span style="color: hsl(120, 100%, 40%);">+         ast_sip_pubsub_has_eventlist_support(rdata), rdata);</span><br><span>         if (!PJSIP_IS_STATUS_IN_CLASS(resp, 200)) {</span><br><span>          pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, resp, NULL, NULL, NULL);</span><br><span>          resource_tree_destroy(&tree);</span><br><span>@@ -3095,6 +3141,7 @@</span><br><span>    sub_tree = create_subscription_tree(handler, endpoint, rdata, resource, generator, &tree, &dlg_status, NULL);</span><br><span>        if (!sub_tree) {</span><br><span>             if (dlg_status != PJ_EEXISTS) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       ast_debug(3, "No dialog exists, rejecting\n");</span><br><span>                     pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);</span><br><span>           }</span><br><span>    } else {</span><br><span>@@ -3331,6 +3378,7 @@</span><br><span>     publication->handler = handler;</span><br><span>   if (publication->handler->publication_state_change(publication, rdata->msg_info.msg->body,</span><br><span>                       AST_SIP_PUBLISH_STATE_INITIALIZED)) {</span><br><span style="color: hsl(120, 100%, 40%);">+         ast_debug(3, "Publication state change failed\n");</span><br><span>                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);</span><br><span>           ao2_cleanup(publication);</span><br><span>            return NULL;</span><br><span>@@ -3760,16 +3808,6 @@</span><br><span>        return PJ_FALSE;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void set_state_terminated(struct ast_sip_subscription *sub)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-    int i;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  sub->subscription_state = PJSIP_EVSUB_STATE_TERMINATED;</span><br><span style="color: hsl(0, 100%, 40%);">-      for (i = 0; i < AST_VECTOR_SIZE(&sub->children); ++i) {</span><br><span style="color: hsl(0, 100%, 40%);">-               set_state_terminated(AST_VECTOR_GET(&sub->children, i));</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> /*!</span><br><span>  * \brief Callback sequence for subscription terminate:</span><br><span>  *</span><br><span>@@ -3852,7 +3890,8 @@</span><br><span> </span><br><span> </span><br><span> /* The code in this function was previously in pubsub_on_evsub_state. */</span><br><span style="color: hsl(0, 100%, 40%);">-static void clean_sub_tree(pjsip_evsub *evsub){</span><br><span style="color: hsl(120, 100%, 40%);">+static void clean_sub_tree(pjsip_evsub *evsub)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span> </span><br><span>         struct sip_subscription_tree *sub_tree;</span><br><span>      sub_tree = pjsip_evsub_get_mod_data(evsub, pubsub_module.id);</span><br><span>@@ -3912,7 +3951,6 @@</span><br><span>                return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>        /* It's easier to write this as what we WANT to process, then negate it. */</span><br><span>      if (!(sub_tree->state == SIP_SUB_TREE_TERMINATE_IN_PROGRESS</span><br><span>               || (event->type == PJSIP_EVENT_TSX_STATE && sub_tree->state == SIP_SUB_TREE_NORMAL)</span><br><span>@@ -3927,9 +3965,8 @@</span><br><span>       This was previously handled by pubsub_on_rx_refresh setting:</span><br><span>         'sub_tree->state = SIP_SUB_TREE_TERMINATE_PENDING' */</span><br><span>  if (event->body.tsx_state.type == PJSIP_EVENT_RX_MSG &&</span><br><span style="color: hsl(0, 100%, 40%);">-          !pjsip_method_cmp(&event->body.tsx_state.tsx->method, &pjsip_subscribe_method) &&</span><br><span style="color: hsl(0, 100%, 40%);">-         pjsip_evsub_get_expires(evsub) == 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+            !pjsip_method_cmp(&event->body.tsx_state.tsx->method, &pjsip_subscribe_method) &&</span><br><span style="color: hsl(120, 100%, 40%);">+               pjsip_evsub_get_expires(evsub) == 0) {</span><br><span>               ast_debug(3, "Subscription ending, do nothing.\n");</span><br><span>                return;</span><br><span>      }</span><br><span>@@ -4058,6 +4095,8 @@</span><br><span>            int *p_st_code, pj_str_t **p_st_text, pjsip_hdr *res_hdr, pjsip_msg_body **p_body)</span><br><span> {</span><br><span>      struct sip_subscription_tree *sub_tree;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ast_sip_subscription_handler *handler = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);</span><br><span> </span><br><span>        sub_tree = pjsip_evsub_get_mod_data(evsub, pubsub_module.id);</span><br><span>        ast_debug(3, "evsub %p sub_tree %p sub_tree state %s\n", evsub, sub_tree,</span><br><span>@@ -4085,25 +4124,32 @@</span><br><span>                sub_tree->state = SIP_SUB_TREE_TERMINATE_PENDING;</span><br><span>         }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ endpoint = ast_pjsip_rdata_get_endpoint(rdata);</span><br><span style="color: hsl(120, 100%, 40%);">+       handler = endpoint ? subscription_get_handler_from_rdata(rdata, ast_sorcery_object_get_id(endpoint)) : NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* If the handler wants a callback on refresh, then do it (some protocols require this). */</span><br><span style="color: hsl(120, 100%, 40%);">+   if (sub_tree->state == SIP_SUB_TREE_NORMAL && handler && handler->notifier->refresh_subscribe) {</span><br><span style="color: hsl(120, 100%, 40%);">+             if (!handler->notifier->refresh_subscribe(sub_tree->root, rdata)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  return; /* If the callback handled it, we're done. */</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  if (sub_tree->state == SIP_SUB_TREE_NORMAL && sub_tree->is_list) {</span><br><span>             /* update RLS */</span><br><span>             const char *resource = sub_tree->root->resource;</span><br><span>               struct ast_sip_subscription *old_root = sub_tree->root;</span><br><span>           struct ast_sip_subscription *new_root = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-           RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);</span><br><span style="color: hsl(0, 100%, 40%);">-               struct ast_sip_subscription_handler *handler = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>               struct ast_sip_pubsub_body_generator *generator = NULL;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-             if ((endpoint = ast_pjsip_rdata_get_endpoint(rdata))</span><br><span style="color: hsl(0, 100%, 40%);">-                    && (handler = subscription_get_handler_from_rdata(rdata, ast_sorcery_object_get_id(endpoint)))</span><br><span style="color: hsl(0, 100%, 40%);">-                  && (generator = subscription_get_generator_from_rdata(rdata, handler))) {</span><br><span style="color: hsl(120, 100%, 40%);">+             if (endpoint && handler && (generator = subscription_get_generator_from_rdata(rdata, handler))) {</span><br><span> </span><br><span>                        struct resource_tree tree;</span><br><span>                   int resp;</span><br><span> </span><br><span>                        memset(&tree, 0, sizeof(tree));</span><br><span>                  resp = build_resource_tree(endpoint, handler, resource, &tree,</span><br><span style="color: hsl(0, 100%, 40%);">-                              ast_sip_pubsub_has_eventlist_support(rdata));</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_sip_pubsub_has_eventlist_support(rdata), rdata);</span><br><span>                         if (PJSIP_IS_STATUS_IN_CLASS(resp, 200)) {</span><br><span>                           new_root = create_virtual_subscriptions(handler, resource, generator, sub_tree, tree.root);</span><br><span>                          if (new_root) {</span><br><span>@@ -5330,7 +5376,7 @@</span><br><span>      }</span><br><span> </span><br><span>        tree = ast_calloc(1, sizeof(*tree));</span><br><span style="color: hsl(0, 100%, 40%);">-    resp = build_resource_tree(NULL, &test_handler, "foo", tree, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+        resp = build_resource_tree(NULL, &test_handler, "foo", tree, 1, NULL);</span><br><span>         if (resp != 200) {</span><br><span>           ast_test_status_update(test, "Unexpected response %d when building resource tree\n", resp);</span><br><span>                return AST_TEST_FAIL;</span><br><span>@@ -5400,7 +5446,7 @@</span><br><span>        }</span><br><span> </span><br><span>        tree = ast_calloc(1, sizeof(*tree));</span><br><span style="color: hsl(0, 100%, 40%);">-    resp = build_resource_tree(NULL, &test_handler, "foo", tree, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+        resp = build_resource_tree(NULL, &test_handler, "foo", tree, 1, NULL);</span><br><span>         if (resp != 200) {</span><br><span>           ast_test_status_update(test, "Unexpected response %d when building resource tree\n", resp);</span><br><span>                return AST_TEST_FAIL;</span><br><span>@@ -5461,7 +5507,7 @@</span><br><span>        }</span><br><span> </span><br><span>        tree = ast_calloc(1, sizeof(*tree));</span><br><span style="color: hsl(0, 100%, 40%);">-    resp = build_resource_tree(NULL, &test_handler, "foo", tree, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+        resp = build_resource_tree(NULL, &test_handler, "foo", tree, 1, NULL);</span><br><span>         if (resp != 200) {</span><br><span>           ast_test_status_update(test, "Unexpected response %d when building resource tree\n", resp);</span><br><span>                return AST_TEST_FAIL;</span><br><span>@@ -5530,7 +5576,7 @@</span><br><span>        }</span><br><span> </span><br><span>        tree = ast_calloc(1, sizeof(*tree));</span><br><span style="color: hsl(0, 100%, 40%);">-    resp = build_resource_tree(NULL, &test_handler, "foo", tree, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+        resp = build_resource_tree(NULL, &test_handler, "foo", tree, 1, NULL);</span><br><span>         if (resp != 200) {</span><br><span>           ast_test_status_update(test, "Unexpected response %d when building resource tree\n", resp);</span><br><span>                return AST_TEST_FAIL;</span><br><span>@@ -5603,7 +5649,7 @@</span><br><span>        }</span><br><span> </span><br><span>        tree = ast_calloc(1, sizeof(*tree));</span><br><span style="color: hsl(0, 100%, 40%);">-    resp = build_resource_tree(NULL, &test_handler, "foo", tree, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+        resp = build_resource_tree(NULL, &test_handler, "foo", tree, 1, NULL);</span><br><span>         if (resp != 200) {</span><br><span>           ast_test_status_update(test, "Unexpected response %d when building resource tree\n", resp);</span><br><span>                return AST_TEST_FAIL;</span><br><span>@@ -5675,7 +5721,7 @@</span><br><span>        }</span><br><span> </span><br><span>        tree = ast_calloc(1, sizeof(*tree));</span><br><span style="color: hsl(0, 100%, 40%);">-    resp = build_resource_tree(NULL, &test_handler, "herp", tree, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+       resp = build_resource_tree(NULL, &test_handler, "herp", tree, 1, NULL);</span><br><span>        if (resp == 200) {</span><br><span>           ast_test_status_update(test, "Unexpected response %d when building resource tree\n", resp);</span><br><span>                return AST_TEST_FAIL;</span><br><span>@@ -5722,7 +5768,7 @@</span><br><span>        /* Since the test_handler is for event "test", this should not build a list, but</span><br><span>    * instead result in a single resource being created, called "foo"</span><br><span>          */</span><br><span style="color: hsl(0, 100%, 40%);">-     resp = build_resource_tree(NULL, &test_handler, "foo", tree, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+        resp = build_resource_tree(NULL, &test_handler, "foo", tree, 1, NULL);</span><br><span>         if (resp != 200) {</span><br><span>           ast_test_status_update(test, "Unexpected response %d when building resource tree\n", resp);</span><br><span>                return AST_TEST_FAIL;</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/20031">change 20031</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/asterisk/+/20031"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I5c54d32223eedab7460ca28616ed50ba4ce1341f </div>
<div style="display:none"> Gerrit-Change-Number: 20031 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: N A <asterisk@phreaknet.org> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>