summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorRichard Mudgett <rmudgett@digium.com>2014-10-03 17:39:50 +0000
committerRichard Mudgett <rmudgett@digium.com>2014-10-03 17:39:50 +0000
commit6a844be566478d6fed1ec93c0836fbf5d5d46ff3 (patch)
treeca7a344f77695f1ecdeaf68cb5c9a6b899562b96 /include
parentb67094624d33b6586177435017cd4f6fdedd3f3f (diff)
chan_pjsip: Fix deadlock when masquerading PJSIP channels.
Performing a directed call pickup resulted in a deadlock when PJSIP channels were involved. A masquerade needs to hold onto the channel locks while it swaps channel information between the two channels involved in the masquerade. With PJSIP channels, the fixup routine needed to push a fixup task onto the PJSIP channel's serializer. Unfortunately, if the serializer was also processing a task that needed to lock the channel, you get deadlock. * Added a new control frame that is used to notify the channels that a masquerade is about to start and when it has completed. * Added the ability to query taskprocessors if the current thread is the taskprocessor thread. * Added the ability to suspend/unsuspend the PJSIP serializer thread so a masquerade could fixup the PJSIP channel without using the serializer. ASTERISK-24356 #close Reported by: rmudgett Review: https://reviewboard.asterisk.org/r/4034/ ........ Merged revisions 424471 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/13@424472 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'include')
-rw-r--r--include/asterisk/frame.h1
-rw-r--r--include/asterisk/res_pjsip_session.h65
-rw-r--r--include/asterisk/taskprocessor.h10
3 files changed, 57 insertions, 19 deletions
diff --git a/include/asterisk/frame.h b/include/asterisk/frame.h
index a981c7e72..20f40f863 100644
--- a/include/asterisk/frame.h
+++ b/include/asterisk/frame.h
@@ -290,6 +290,7 @@ enum ast_control_frame_type {
AST_CONTROL_MCID = 31, /*!< Indicate that the caller is being malicious. */
AST_CONTROL_UPDATE_RTP_PEER = 32, /*!< Interrupt the bridge and have it update the peer */
AST_CONTROL_PVT_CAUSE_CODE = 33, /*!< Contains an update to the protocol-specific cause-code stored for branching dials */
+ AST_CONTROL_MASQUERADE_NOTIFY = 34, /*!< A masquerade is about to begin/end. (Never sent as a frame but directly with ast_indicate_data().) */
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
diff --git a/include/asterisk/res_pjsip_session.h b/include/asterisk/res_pjsip_session.h
index 010a74dc0..3344a6b38 100644
--- a/include/asterisk/res_pjsip_session.h
+++ b/include/asterisk/res_pjsip_session.h
@@ -87,6 +87,9 @@ struct ast_sip_session_media {
*/
struct ast_sip_session_delayed_request;
+/*! \brief Opaque struct controlling the suspension of the session's serializer. */
+struct ast_sip_session_suspender;
+
/*!
* \brief A structure describing a SIP session
*
@@ -96,43 +99,45 @@ struct ast_sip_session_delayed_request;
* to use the term "SIP session" to refer to the INVITE dialog itself.
*/
struct ast_sip_session {
- /* Dialplan extension where incoming call is destined */
+ /*! Dialplan extension where incoming call is destined */
char exten[AST_MAX_EXTENSION];
- /* The endpoint with which Asterisk is communicating */
+ /*! The endpoint with which Asterisk is communicating */
struct ast_sip_endpoint *endpoint;
- /* The contact associated with this session */
+ /*! The contact associated with this session */
struct ast_sip_contact *contact;
- /* The PJSIP details of the session, which includes the dialog */
+ /*! The PJSIP details of the session, which includes the dialog */
struct pjsip_inv_session *inv_session;
- /* The Asterisk channel associated with the session */
+ /*! The Asterisk channel associated with the session */
struct ast_channel *channel;
- /* Registered session supplements */
+ /*! Registered session supplements */
AST_LIST_HEAD(, ast_sip_session_supplement) supplements;
- /* Datastores added to the session by supplements to the session */
+ /*! Datastores added to the session by supplements to the session */
struct ao2_container *datastores;
- /* Media streams */
+ /*! Media streams */
struct ao2_container *media;
- /* Serializer for tasks relating to this SIP session */
+ /*! Serializer for tasks relating to this SIP session */
struct ast_taskprocessor *serializer;
- /* Requests that could not be sent due to current inv_session state */
+ /*! Non-null if the session serializer is suspended or being suspended. */
+ struct ast_sip_session_suspender *suspended;
+ /*! Requests that could not be sent due to current inv_session state */
AST_LIST_HEAD_NOLOCK(, ast_sip_session_delayed_request) delayed_requests;
- /* When we need to reschedule a reinvite, we use this structure to do it */
+ /*! When we need to reschedule a reinvite, we use this structure to do it */
pj_timer_entry rescheduled_reinvite;
- /* Format capabilities pertaining to direct media */
+ /*! Format capabilities pertaining to direct media */
struct ast_format_cap *direct_media_cap;
- /* When we need to forcefully end the session */
+ /*! When we need to forcefully end the session */
pj_timer_entry scheduled_termination;
- /* Identity of endpoint this session deals with */
+ /*! Identity of endpoint this session deals with */
struct ast_party_id id;
- /* Requested capabilities */
+ /*! Requested capabilities */
struct ast_format_cap *req_caps;
- /* Optional DSP, used only for inband DTMF detection if configured */
+ /*! Optional DSP, used only for inband DTMF detection if configured */
struct ast_dsp *dsp;
- /* Whether the termination of the session should be deferred */
+ /*! Whether the termination of the session should be deferred */
unsigned int defer_terminate:1;
- /* Deferred incoming re-invite */
+ /*! Deferred incoming re-invite */
pjsip_rx_data *deferred_reinvite;
- /* Current T.38 state */
+ /*! Current T.38 state */
enum ast_sip_session_t38state t38state;
};
@@ -388,6 +393,28 @@ struct ast_sip_session *ast_sip_session_alloc(struct ast_sip_endpoint *endpoint,
struct ast_sip_contact *contact, pjsip_inv_session *inv);
/*!
+ * \brief Request and wait for the session serializer to be suspended.
+ * \since 12.7.0
+ *
+ * \param session Which session to suspend the serializer.
+ *
+ * \note No channel locks can be held while calling without risk of deadlock.
+ *
+ * \return Nothing
+ */
+void ast_sip_session_suspend(struct ast_sip_session *session);
+
+/*!
+ * \brief Request the session serializer be unsuspended.
+ * \since 12.7.0
+ *
+ * \param session Which session to unsuspend the serializer.
+ *
+ * \return Nothing
+ */
+void ast_sip_session_unsuspend(struct ast_sip_session *session);
+
+/*!
* \brief Create a new outgoing SIP session
*
* The endpoint that is passed in will have its reference count increased by one since
diff --git a/include/asterisk/taskprocessor.h b/include/asterisk/taskprocessor.h
index ab523290c..f16f144cb 100644
--- a/include/asterisk/taskprocessor.h
+++ b/include/asterisk/taskprocessor.h
@@ -247,6 +247,16 @@ int ast_taskprocessor_push_local(struct ast_taskprocessor *tps,
int ast_taskprocessor_execute(struct ast_taskprocessor *tps);
/*!
+ * \brief Am I the given taskprocessor's current task.
+ * \since 12.7.0
+ *
+ * \param tps Taskprocessor to check.
+ *
+ * \retval non-zero if current thread is the taskprocessor thread.
+ */
+int ast_taskprocessor_is_task(struct ast_taskprocessor *tps);
+
+/*!
* \brief Return the name of the taskprocessor singleton
* \since 1.6.1
*/