diff --git a/include/asterisk/utils.h b/include/asterisk/utils.h index f8f761d39f..379ae83196 100644 --- a/include/asterisk/utils.h +++ b/include/asterisk/utils.h @@ -1195,4 +1195,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 f353f0e0cf..40e40454d3 100644 --- a/main/autoservice.c +++ b/main/autoservice.c @@ -195,6 +195,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) { @@ -256,6 +263,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 7c3efb4502..c5ab0b6036 100644 --- a/main/tcptls.c +++ b/main/tcptls.c @@ -685,6 +685,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; + } + tcptls_session->stream_cookie = tcptls_stream_alloc(); if (!tcptls_session->stream_cookie) { ast_tcptls_close_session_file(tcptls_session); diff --git a/main/utils.c b/main/utils.c index 2e612c111f..ba16e41f18 100644 --- a/main/utils.c +++ b/main/utils.c @@ -2833,3 +2833,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; +}