res_pjsip_refer: Make safely get the context for a blind transfer.
authorRichard Mudgett <rmudgett@digium.com>
Fri, 6 Mar 2015 22:59:29 +0000 (22:59 +0000)
committerRichard Mudgett <rmudgett@digium.com>
Fri, 6 Mar 2015 22:59:29 +0000 (22:59 +0000)
Made safely get the TRANSFER_CONTEXT channel value while the channel is
locked in refer_incoming_attended_request() and
refer_incoming_blind_request().  The pointer returned by
pbx_builtin_getvar_helper() is only valid while the channel is locked.
........

Merged revisions 432594 from http://svn.asterisk.org/svn/asterisk/branches/13

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@432595 65c4cc65-6c06-0410-ace0-fbb531ad65f3

res/res_pjsip_refer.c

index bc4e0e7..c1b76ae 100644 (file)
@@ -628,6 +628,26 @@ static void refer_blind_callback(struct ast_channel *chan, struct transfer_chann
        }
 }
 
+/*!
+ * \internal
+ * \brief Set the passed in context variable to the determined transfer context.
+ * \since 13.3.0
+ *
+ * \param context Set to the determined transfer context.
+ * \param session INVITE dialog SIP session.
+ */
+#define DETERMINE_TRANSFER_CONTEXT(context, session)                                                                   \
+       do {                                                                                                                                                            \
+               ast_channel_lock((session)->channel);                                                                                   \
+               context = pbx_builtin_getvar_helper((session)->channel, "TRANSFER_CONTEXT");    \
+               if (ast_strlen_zero(context)) {                                                                                                 \
+                       context = (session)->endpoint->context;                                                                         \
+               } else {                                                                                                                                                \
+                       context = ast_strdupa(context);                                                                                         \
+               }                                                                                                                                                               \
+               ast_channel_unlock((session)->channel);                                                                                 \
+       } while (0)                                                                                                                                                     \
+
 static int refer_incoming_attended_request(struct ast_sip_session *session, pjsip_rx_data *rdata, pjsip_sip_uri *target_uri,
        pjsip_param *replaces_param, struct refer_progress *progress)
 {
@@ -678,12 +698,10 @@ static int refer_incoming_attended_request(struct ast_sip_session *session, pjsi
 
                return 200;
        } else {
-               const char *context = pbx_builtin_getvar_helper(session->channel, "TRANSFER_CONTEXT");
+               const char *context;
                struct refer_blind refer = { 0, };
 
-               if (ast_strlen_zero(context)) {
-                       context = session->endpoint->context;
-               }
+               DETERMINE_TRANSFER_CONTEXT(context, session);
 
                if (!ast_exists_extension(NULL, context, "external_replaces", 1, NULL)) {
                        ast_log(LOG_ERROR, "Received REFER for remote session on channel '%s' from endpoint '%s' but 'external_replaces' extension not found in context %s\n",
@@ -721,10 +739,7 @@ static int refer_incoming_blind_request(struct ast_sip_session *session, pjsip_r
        struct refer_blind refer = { 0, };
 
        /* If no explicit transfer context has been provided use their configured context */
-       context = pbx_builtin_getvar_helper(session->channel, "TRANSFER_CONTEXT");
-       if (ast_strlen_zero(context)) {
-               context = session->endpoint->context;
-       }
+       DETERMINE_TRANSFER_CONTEXT(context, session);
 
        /* Using the user portion of the target URI see if it exists as a valid extension in their context */
        ast_copy_pj_str(exten, &target->user, sizeof(exten));