Index: main/tcptls.c =================================================================== --- main/tcptls.c (revision 155920) +++ main/tcptls.c (working copy) @@ -43,7 +43,11 @@ #include "asterisk/options.h" #include "asterisk/manager.h" #include "asterisk/astobj2.h" +#include "asterisk/sched.h" +struct sched_context *sched = NULL; +pthread_t monitor_thread = AST_PTHREADT_NULL; + /*! \brief * replacement read/write functions for SSL support. * We use wrappers rather than SSL_read/SSL_write directly so @@ -269,6 +273,18 @@ return NULL; } +static void *do_monitor(void *data) +{ + int res; + for (;;) { + if ((res = ast_sched_wait(sched)) != 0) { + poll(NULL, 0, res); + } + ast_sched_runq(sched); + } + return NULL; +} + static int __ssl_setup(struct ast_tls_config *cfg, int client) { #ifndef DO_SSL @@ -278,6 +294,14 @@ if (!cfg->enabled) return 0; + if (monitor_thread == AST_PTHREADT_NULL) { + sched = sched_context_create(); + if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { + ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); + return 0; + } + } + SSL_load_error_strings(); SSLeay_add_ssl_algorithms(); @@ -324,6 +348,19 @@ return __ssl_setup(cfg, 0); } +struct send_sigurg { + pthread_t tid; + int schedid; +}; + +static int send_sigurg(const void *vid) +{ + struct send_sigurg *ssu = (void *)vid; + pthread_kill(ssu->tid, SIGURG); + ssu->schedid = -1; + return 0; +} + /*! \brief A generic client routine for a TCP client * and starts a thread for handling accept() */ @@ -332,6 +369,7 @@ int flags; int x = 1; struct ast_tcptls_session_instance *ser = NULL; + struct send_sigurg ssu = { .schedid = -1, .tid = pthread_self() }; /* Do nothing if nothing has changed */ if(!memcmp(&desc->old_local_address, &desc->local_address, sizeof(desc->old_local_address))) { @@ -364,13 +402,19 @@ } } + /* Don't allow the connect to hang, if the TCP connection stalls. */ + ssu.schedid = ast_sched_add(sched, 2000, send_sigurg, &ssu); + pthread_kill(monitor_thread, SIGURG); + if (connect(desc->accept_fd, (const struct sockaddr *) &desc->remote_address, sizeof(desc->remote_address))) { ast_log(LOG_ERROR, "Unable to connect %s to %s:%d: %s\n", desc->name, ast_inet_ntoa(desc->remote_address.sin_addr), ntohs(desc->remote_address.sin_port), strerror(errno)); + AST_SCHED_DEL(sched, ssu.schedid); goto error; } + AST_SCHED_DEL(sched, ssu.schedid); if (!(ser = ao2_alloc(sizeof(*ser), session_instance_destructor))) goto error;