<p>Friendly Automation <strong>submitted</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/15196">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Joshua Colp: Looks good to me, but someone else must approve
  George Joseph: Looks good to me, approved
  Friendly Automation: Approved for Submit

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">chan_pjsip: Incorporate channel reference count into transfer_refer().<br><br>Add channel reference count for PJSIP REFER. The call could be terminated<br>prior to the result of the transfer. In that scenario, when the SUBSCRIBE/NOTIFY<br>occurred several minutes later, it would attempt to access a session which was<br>no longer valid.  Terminate event subscription if pjsip_xfer_initiate() or<br>pjsip_xfer_send_request() fails in transfer_refer().<br><br>ASTERISK-29201 #close<br>Reported-by: Dan Cropp<br><br>Change-Id: I3fd92fd14b4e3844d3d7b0f60fe417a4df5f2435<br>---<br>M channels/chan_pjsip.c<br>1 file changed, 26 insertions(+), 18 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c</span><br><span>index b6944db..bb04d73 100644</span><br><span>--- a/channels/chan_pjsip.c</span><br><span>+++ b/channels/chan_pjsip.c</span><br><span>@@ -1922,8 +1922,7 @@</span><br><span>  */</span><br><span> static void xfer_client_on_evsub_state(pjsip_evsub *sub, pjsip_event *event)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_sip_session *session;</span><br><span style="color: hsl(0, 100%, 40%);">-        struct ast_channel *chan = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ast_channel *chan;</span><br><span>    enum ast_control_transfer message = AST_TRANSFER_SUCCESS;</span><br><span>    int res = 0;</span><br><span> </span><br><span>@@ -1931,12 +1930,7 @@</span><br><span>            return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   session = pjsip_evsub_get_mod_data(sub, refer_callback_module.id);</span><br><span style="color: hsl(0, 100%, 40%);">-      if (!session) {</span><br><span style="color: hsl(0, 100%, 40%);">-         return;</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%);">-       chan = session->channel;</span><br><span style="color: hsl(120, 100%, 40%);">+   chan = pjsip_evsub_get_mod_data(sub, refer_callback_module.id);</span><br><span>      if (!chan) {</span><br><span>                 return;</span><br><span>      }</span><br><span>@@ -1962,7 +1956,9 @@</span><br><span>                     */</span><br><span>                  if (refer_sub && !pj_stricmp2(&refer_sub->hvalue, "false")) {</span><br><span>                               /* Since no subscription is desired, assume that call has been transferred successfully. */</span><br><span style="color: hsl(120, 100%, 40%);">+                           /* Channel reference will be released at end of function */</span><br><span>                          /* Terminate subscription. */</span><br><span style="color: hsl(120, 100%, 40%);">+                         pjsip_evsub_set_mod_data(sub, refer_callback_module.id, NULL);</span><br><span>                               pjsip_evsub_terminate(sub, PJ_TRUE);</span><br><span>                                 res = -1;</span><br><span>                    }</span><br><span>@@ -2027,7 +2023,8 @@</span><br><span>    }</span><br><span> </span><br><span>        if (res) {</span><br><span style="color: hsl(0, 100%, 40%);">-              ast_queue_control_data(session->channel, AST_CONTROL_TRANSFER, &message, sizeof(message));</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_queue_control_data(chan, AST_CONTROL_TRANSFER, &message, sizeof(message));</span><br><span style="color: hsl(120, 100%, 40%);">+            ao2_ref(chan, -1);</span><br><span>   }</span><br><span> }</span><br><span> </span><br><span>@@ -2040,28 +2037,29 @@</span><br><span>         const char *ref_by_val;</span><br><span>      char local_info[pj_strlen(&session->inv_session->dlg->local.info_str) + 1];</span><br><span>     struct pjsip_evsub_user xfer_cb;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ast_channel *chan = session->channel;</span><br><span> </span><br><span>  pj_bzero(&xfer_cb, sizeof(xfer_cb));</span><br><span>     xfer_cb.on_evsub_state = &xfer_client_on_evsub_state;</span><br><span> </span><br><span>        if (pjsip_xfer_create_uac(session->inv_session->dlg, &xfer_cb, &sub) != PJ_SUCCESS) {</span><br><span>          message = AST_TRANSFER_FAILED;</span><br><span style="color: hsl(0, 100%, 40%);">-          ast_queue_control_data(session->channel, AST_CONTROL_TRANSFER, &message, sizeof(message));</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_queue_control_data(chan, AST_CONTROL_TRANSFER, &message, sizeof(message));</span><br><span> </span><br><span>               return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   pjsip_evsub_set_mod_data(sub, refer_callback_module.id, session);</span><br><span style="color: hsl(120, 100%, 40%);">+     /* refer_callback_module requires a reference to chan</span><br><span style="color: hsl(120, 100%, 40%);">+  * which will be released in xfer_client_on_evsub_state()</span><br><span style="color: hsl(120, 100%, 40%);">+      * when the implicit REFER subscription terminates */</span><br><span style="color: hsl(120, 100%, 40%);">+ pjsip_evsub_set_mod_data(sub, refer_callback_module.id, chan);</span><br><span style="color: hsl(120, 100%, 40%);">+        ao2_ref(chan, +1);</span><br><span> </span><br><span>       if (pjsip_xfer_initiate(sub, pj_cstr(&tmp, target), &packet) != PJ_SUCCESS) {</span><br><span style="color: hsl(0, 100%, 40%);">-           message = AST_TRANSFER_FAILED;</span><br><span style="color: hsl(0, 100%, 40%);">-          ast_queue_control_data(session->channel, AST_CONTROL_TRANSFER, &message, sizeof(message));</span><br><span style="color: hsl(0, 100%, 40%);">-               pjsip_evsub_terminate(sub, PJ_FALSE);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-           return;</span><br><span style="color: hsl(120, 100%, 40%);">+               goto failure;</span><br><span>        }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   ref_by_val = pbx_builtin_getvar_helper(session->channel, "SIPREFERREDBYHDR");</span><br><span style="color: hsl(120, 100%, 40%);">+    ref_by_val = pbx_builtin_getvar_helper(chan, "SIPREFERREDBYHDR");</span><br><span>  if (!ast_strlen_zero(ref_by_val)) {</span><br><span>          ast_sip_add_header(packet, "Referred-By", ref_by_val);</span><br><span>     } else {</span><br><span>@@ -2069,7 +2067,17 @@</span><br><span>            ast_sip_add_header(packet, "Referred-By", local_info);</span><br><span>     }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   pjsip_xfer_send_request(sub, packet);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (pjsip_xfer_send_request(sub, packet) == PJ_SUCCESS) {</span><br><span style="color: hsl(120, 100%, 40%);">+             return;</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%);">+failure:</span><br><span style="color: hsl(120, 100%, 40%);">+ message = AST_TRANSFER_FAILED;</span><br><span style="color: hsl(120, 100%, 40%);">+        ast_queue_control_data(chan, AST_CONTROL_TRANSFER, &message, sizeof(message));</span><br><span style="color: hsl(120, 100%, 40%);">+    pjsip_evsub_set_mod_data(sub, refer_callback_module.id, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+        pjsip_evsub_terminate(sub, PJ_FALSE);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       ao2_ref(chan, -1);</span><br><span> }</span><br><span> </span><br><span> static int transfer(void *data)</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/15196">change 15196</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/+/15196"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 18 </div>
<div style="display:none"> Gerrit-Change-Id: I3fd92fd14b4e3844d3d7b0f60fe417a4df5f2435 </div>
<div style="display:none"> Gerrit-Change-Number: 15196 </div>
<div style="display:none"> Gerrit-PatchSet: 5 </div>
<div style="display:none"> Gerrit-Owner: Dan Cropp <dan@amtelco.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@sangoma.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>