diff --git a/include/asterisk/utils.h b/include/asterisk/utils.h index b892cda9e4..6f9a11e936 100644 --- a/include/asterisk/utils.h +++ b/include/asterisk/utils.h @@ -913,4 +913,22 @@ enum ast_fd_flag_operation { int __ast_fd_set_flags(int fd, int flags, enum ast_fd_flag_operation op, const char *file, int lineno, const char *function); +/*! + * \brief Set the current thread's user interface status. + * + * \param is_user_interface Non-zero to mark the thread as a user interface. + * + * \return 0 if successfuly marked current thread. + * \return Non-zero if marking current thread failed. + */ +int ast_thread_user_interface_set(int is_user_interface); + +/*! + * \brief Indicates whether the current thread is a user interface + * + * \return True (non-zero) if thread is a user interface. + * \return False (zero) if thread is not a user interface. + */ +int ast_thread_is_user_interface(void); + #endif /* _ASTERISK_UTILS_H */ diff --git a/main/autoservice.c b/main/autoservice.c index cd7388b7dd..8ff2cb56e1 100644 --- a/main/autoservice.c +++ b/main/autoservice.c @@ -202,6 +202,13 @@ int ast_autoservice_start(struct ast_channel *chan) int res = 0; struct asent *as; + if (ast_thread_is_user_interface()) { + /* User interface threads do not handle channel media. */ + ast_debug(1, "Thread is a user interface, not putting channel %s into autoservice\n", + ast_channel_name(chan)); + return 0; + } + AST_LIST_LOCK(&aslist); AST_LIST_TRAVERSE(&aslist, as, list) { if (as->chan == chan) { @@ -263,6 +270,13 @@ int ast_autoservice_stop(struct ast_channel *chan) struct ast_frame *f; int chan_list_state; + if (ast_thread_is_user_interface()) { + /* User interface threads do not handle channel media. */ + ast_debug(1, "Thread is a user interface, not removing channel %s from autoservice\n", + ast_channel_name(chan)); + return 0; + } + AST_LIST_LOCK(&aslist); /* Save the autoservice channel list state. We _must_ verify that the channel diff --git a/main/tcptls.c b/main/tcptls.c index f5557307e0..3ba52ff6a3 100644 --- a/main/tcptls.c +++ b/main/tcptls.c @@ -134,6 +134,19 @@ static void *handle_tcptls_connection(void *data) return NULL; } + /* + * TCP/TLS connections are associated with external protocols which can + * be considered to be user interfaces (even for SIP messages), and + * will not handle channel media. This may need to be pushed down into + * the individual protocol handlers, but this seems like a good start. + */ + if (ast_thread_user_interface_set(1)) { + ast_log(LOG_ERROR, "Failed to set user interface status; killing connection\n"); + ast_tcptls_close_session_file(tcptls_session); + ao2_ref(tcptls_session, -1); + return NULL; + } + if (tcptls_session->parent->tls_cfg) { #ifdef DO_SSL if (ast_iostream_start_tls(&tcptls_session->stream, tcptls_session->parent->tls_cfg->ssl_ctx, tcptls_session->client) < 0) { diff --git a/main/utils.c b/main/utils.c index 6ecd2b82e5..2eaf1f9e25 100644 --- a/main/utils.c +++ b/main/utils.c @@ -2750,3 +2750,38 @@ int __ast_fd_set_flags(int fd, int flags, enum ast_fd_flag_operation op, return 0; } + +/*! + * \brief A thread local indicating whether the current thread is a user interface. + */ +AST_THREADSTORAGE(thread_user_interface_tl); + +int ast_thread_user_interface_set(int is_user_interface) +{ + int *thread_user_interface; + + thread_user_interface = ast_threadstorage_get( + &thread_user_interface_tl, sizeof(*thread_user_interface)); + if (thread_user_interface == NULL) { + ast_log(LOG_ERROR, "Error setting user interface status for current thread\n"); + return -1; + } + + *thread_user_interface = !!is_user_interface; + return 0; +} + +int ast_thread_is_user_interface(void) +{ + int *thread_user_interface; + + thread_user_interface = ast_threadstorage_get( + &thread_user_interface_tl, sizeof(*thread_user_interface)); + if (thread_user_interface == NULL) { + ast_log(LOG_ERROR, "Error checking thread's user interface status\n"); + /* On error, assume that we are not a user interface thread */ + return 0; + } + + return *thread_user_interface; +}