summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/app_chanspy.c8
-rw-r--r--apps/app_mixmonitor.c8
-rw-r--r--include/asterisk/autochan.h20
-rw-r--r--main/autochan.c6
-rw-r--r--res/res_pjsip_refer.c21
5 files changed, 45 insertions, 18 deletions
diff --git a/apps/app_chanspy.c b/apps/app_chanspy.c
index 3c7a91716..5dbb0b860 100644
--- a/apps/app_chanspy.c
+++ b/apps/app_chanspy.c
@@ -598,12 +598,12 @@ static int attach_barge(struct ast_autochan *spyee_autochan,
return -1;
}
- ast_channel_lock(internal_bridge_autochan->chan);
+ ast_autochan_channel_lock(internal_bridge_autochan);
if (start_spying(internal_bridge_autochan, spyer_name, bridge_whisper_audiohook)) {
ast_log(LOG_WARNING, "Unable to attach barge audiohook on spyee '%s'. Barge mode disabled.\n", name);
retval = -1;
}
- ast_channel_unlock(internal_bridge_autochan->chan);
+ ast_autochan_channel_unlock(internal_bridge_autochan);
*spyee_bridge_autochan = internal_bridge_autochan;
@@ -632,9 +632,9 @@ static int channel_spy(struct ast_channel *chan, struct ast_autochan *spyee_auto
spyer_name = ast_strdupa(ast_channel_name(chan));
ast_channel_unlock(chan);
- ast_channel_lock(spyee_autochan->chan);
+ ast_autochan_channel_lock(spyee_autochan);
name = ast_strdupa(ast_channel_name(spyee_autochan->chan));
- ast_channel_unlock(spyee_autochan->chan);
+ ast_autochan_channel_unlock(spyee_autochan);
ast_verb(2, "Spying on channel %s\n", name);
publish_chanspy_message(chan, spyee_autochan->chan, 1);
diff --git a/apps/app_mixmonitor.c b/apps/app_mixmonitor.c
index f5f9b22c1..7d7a0cbf9 100644
--- a/apps/app_mixmonitor.c
+++ b/apps/app_mixmonitor.c
@@ -726,11 +726,11 @@ static void *mixmonitor_thread(void *obj)
ast_audiohook_unlock(&mixmonitor->audiohook);
- ast_channel_lock(mixmonitor->autochan->chan);
+ ast_autochan_channel_lock(mixmonitor->autochan);
if (ast_test_flag(mixmonitor, MUXFLAG_BEEP_STOP)) {
ast_stream_and_wait(mixmonitor->autochan->chan, "beep", "");
}
- ast_channel_unlock(mixmonitor->autochan->chan);
+ ast_autochan_channel_unlock(mixmonitor->autochan);
ast_autochan_destroy(mixmonitor->autochan);
@@ -802,11 +802,11 @@ static int setup_mixmonitor_ds(struct mixmonitor *mixmonitor, struct ast_channel
return -1;
}
- ast_channel_lock(mixmonitor->autochan->chan);
+ ast_autochan_channel_lock(mixmonitor->autochan);
if (ast_test_flag(mixmonitor, MUXFLAG_BEEP_START)) {
ast_stream_and_wait(mixmonitor->autochan->chan, "beep", "");
}
- ast_channel_unlock(mixmonitor->autochan->chan);
+ ast_autochan_channel_unlock(mixmonitor->autochan);
mixmonitor_ds->samp_rate = 8000;
mixmonitor_ds->audiohook = &mixmonitor->audiohook;
diff --git a/include/asterisk/autochan.h b/include/asterisk/autochan.h
index a0981b7c9..319c203ab 100644
--- a/include/asterisk/autochan.h
+++ b/include/asterisk/autochan.h
@@ -56,8 +56,28 @@ struct ast_autochan {
* to save off the pointer using ast_channel_ref and to unref the channel when you
* are finished with the pointer. If you do not do this and a masquerade occurs on
* the channel, then it is possible that your saved pointer will become invalid.
+ *
+ * 3. If you want to lock the autochan->chan channel, be sure to use
+ * ast_autochan_channel_lock and ast_autochan_channel_unlock. An attempt to lock
+ * the autochan->chan directly may result in it being changed after you've
+ * retrieved the value of chan, but before you've had a chance to lock it.
+ * First when chan is locked, the autochan structure is guaranteed to keep the
+ * same channel.
*/
+#define ast_autochan_channel_lock(autochan) \
+ do { \
+ struct ast_channel *autochan_chan = autochan->chan; \
+ ast_channel_lock(autochan_chan); \
+ if (autochan->chan == autochan_chan) { \
+ break; \
+ } \
+ ast_channel_unlock(autochan_chan); \
+ } while (1)
+
+#define ast_autochan_channel_unlock(autochan) \
+ ast_channel_unlock(autochan->chan)
+
/*!
* \brief set up a new ast_autochan structure
*
diff --git a/main/autochan.c b/main/autochan.c
index d41a8d821..38d778438 100644
--- a/main/autochan.c
+++ b/main/autochan.c
@@ -51,7 +51,7 @@ struct ast_autochan *ast_autochan_setup(struct ast_channel *chan)
autochan->chan = ast_channel_ref(chan);
- ast_channel_lock(autochan->chan);
+ ast_channel_lock(autochan->chan); /* autochan is still private, no need for ast_autochan_channel_lock() */
AST_LIST_INSERT_TAIL(ast_channel_autochans(autochan->chan), autochan, list);
ast_channel_unlock(autochan->chan);
@@ -64,7 +64,7 @@ void ast_autochan_destroy(struct ast_autochan *autochan)
{
struct ast_autochan *autochan_iter;
- ast_channel_lock(autochan->chan);
+ ast_autochan_channel_lock(autochan);
AST_LIST_TRAVERSE_SAFE_BEGIN(ast_channel_autochans(autochan->chan), autochan_iter, list) {
if (autochan_iter == autochan) {
AST_LIST_REMOVE_CURRENT(list);
@@ -73,7 +73,7 @@ void ast_autochan_destroy(struct ast_autochan *autochan)
}
}
AST_LIST_TRAVERSE_SAFE_END;
- ast_channel_unlock(autochan->chan);
+ ast_autochan_channel_unlock(autochan);
autochan->chan = ast_channel_unref(autochan->chan);
diff --git a/res/res_pjsip_refer.c b/res/res_pjsip_refer.c
index f89f901cf..fbc3eb3e2 100644
--- a/res/res_pjsip_refer.c
+++ b/res/res_pjsip_refer.c
@@ -59,6 +59,8 @@ struct refer_progress {
struct transfer_channel_data *transfer_data;
/*! \brief Uniqueid of transferee channel */
char *transferee;
+ /*! \brief Non-zero if the 100 notify has been sent */
+ int sent_100;
};
/*! \brief REFER Progress notification structure */
@@ -133,6 +135,18 @@ static int refer_progress_notify(void *data)
notification->progress->sub = NULL;
}
+ /* Send a deferred initial 100 Trying SIP frag NOTIFY if we haven't already. */
+ if (!notification->progress->sent_100) {
+ notification->progress->sent_100 = 1;
+ if (notification->response != 100) {
+ ast_debug(3, "Sending initial 100 Trying NOTIFY for progress monitor '%p'\n",
+ notification->progress);
+ if (pjsip_xfer_notify(sub, PJSIP_EVSUB_STATE_ACTIVE, 100, NULL, &tdata) == PJ_SUCCESS) {
+ pjsip_xfer_send_request(sub, tdata);
+ }
+ }
+ }
+
ast_debug(3, "Sending NOTIFY with response '%d' and state '%u' on subscription '%p' and progress monitor '%p'\n",
notification->response, notification->state, sub, notification->progress);
@@ -340,7 +354,6 @@ static int refer_progress_alloc(struct ast_sip_session *session, pjsip_rx_data *
const pj_str_t str_refer_sub = { "Refer-Sub", 9 };
pjsip_generic_string_hdr *refer_sub = NULL;
const pj_str_t str_true = { "true", 4 };
- pjsip_tx_data *tdata;
pjsip_hdr hdr_list;
char tps_name[AST_TASKPROCESSOR_MAX_NAME + 1];
@@ -392,12 +405,6 @@ static int refer_progress_alloc(struct ast_sip_session *session, pjsip_rx_data *
ast_debug(3, "Accepting REFER request for progress monitor '%p'\n", *progress);
pjsip_xfer_accept((*progress)->sub, rdata, 202, &hdr_list);
- /* Send initial NOTIFY Request */
- ast_debug(3, "Sending initial 100 Trying NOTIFY for progress monitor '%p'\n", *progress);
- if (pjsip_xfer_notify((*progress)->sub, PJSIP_EVSUB_STATE_ACTIVE, 100, NULL, &tdata) == PJ_SUCCESS) {
- pjsip_xfer_send_request((*progress)->sub, tdata);
- }
-
return 0;
error: