From ec443a41d0742008686a02e9ba90456d36aa336b Mon Sep 17 00:00:00 2001 From: Richard Mudgett <rmudgett@digium.com> Date: Fri, 13 Jun 2014 05:29:30 +0000 Subject: [PATCH] AST-2014-007: Fix of fix to allow AMI and SIP TCP to send messages. ASTERISK-23673 #close Reported by: Richard Mudgett Review: https://reviewboard.asterisk.org/r/3617/ ........ Merged revisions 416066 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 416067 from http://svn.asterisk.org/svn/asterisk/branches/11 git-svn-id: https://origsvn.digium.com/svn/asterisk/certified/branches/11.6@416106 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channels/chan_sip.c | 6 ++++++ include/asterisk/tcptls.h | 16 +++++++++++++++- main/http.c | 3 +++ main/manager.c | 6 ++++++ main/tcptls.c | 17 ++++++++++++++++- 5 files changed, 46 insertions(+), 2 deletions(-) diff --git a/channels/chan_sip.c b/channels/chan_sip.c index df20b83901..5a71388d5b 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -3109,6 +3109,12 @@ static void *_sip_tcp_helper_thread(struct ast_tcptls_session_instance *tcptls_s goto cleanup; } + /* + * We cannot let the stream exclusively wait for data to arrive. + * We have to wake up the task to send outgoing messages. + */ + ast_tcptls_stream_set_exclusive_input(tcptls_session->stream_cookie, 0); + ast_tcptls_stream_set_timeout_sequence(tcptls_session->stream_cookie, ast_tvnow(), tcptls_session->client ? -1 : (authtimeout * 1000)); diff --git a/include/asterisk/tcptls.h b/include/asterisk/tcptls.h index 17b532cdab..3356a92ccd 100644 --- a/include/asterisk/tcptls.h +++ b/include/asterisk/tcptls.h @@ -189,7 +189,21 @@ void ast_tcptls_stream_set_timeout_inactivity(struct ast_tcptls_stream *stream, */ void ast_tcptls_stream_set_timeout_sequence(struct ast_tcptls_stream *stream, struct timeval start, int timeout); -/*! \brief +/*! + * \brief Set the TCP/TLS stream I/O if it can exclusively depend upon the set timeouts. + * + * \param stream TCP/TLS stream control data. + * \param exclusive_input TRUE if stream can exclusively wait for fd input. + * Otherwise, the stream will not wait for fd input. It will wait while + * trying to send data. + * + * \note The stream timeouts still need to be set. + * + * \return Nothing + */ +void ast_tcptls_stream_set_exclusive_input(struct ast_tcptls_stream *stream, int exclusive_input); + +/*! \brief * describes a server instance */ struct ast_tcptls_session_instance { diff --git a/main/http.c b/main/http.c index ffc03fceab..a123dd28c5 100644 --- a/main/http.c +++ b/main/http.c @@ -877,6 +877,9 @@ static void *httpd_helper_thread(void *data) flags |= O_NONBLOCK; fcntl(ser->fd, F_SETFL, flags); + /* We can let the stream wait for data to arrive. */ + ast_tcptls_stream_set_exclusive_input(ser->stream_cookie, 1); + ast_tcptls_stream_set_timeout_inactivity(ser->stream_cookie, session_inactivity); if (!fgets(buf, sizeof(buf), ser->f) || feof(ser->f)) { diff --git a/main/manager.c b/main/manager.c index fe67d5c5cf..51a3b4292a 100644 --- a/main/manager.c +++ b/main/manager.c @@ -5562,6 +5562,12 @@ static void *session_do(void *data) } ao2_unlock(session); + /* + * We cannot let the stream exclusively wait for data to arrive. + * We have to wake up the task to send async events. + */ + ast_tcptls_stream_set_exclusive_input(ser->stream_cookie, 0); + ast_tcptls_stream_set_timeout_sequence(ser->stream_cookie, ast_tvnow(), authtimeout * 1000); diff --git a/main/tcptls.c b/main/tcptls.c index 83c21cf8da..65101f4c9c 100644 --- a/main/tcptls.c +++ b/main/tcptls.c @@ -77,6 +77,8 @@ struct ast_tcptls_stream { * feature to work correctly. */ int timeout; + /*! TRUE if stream can exclusively wait for fd input. */ + int exclusive_input; }; void ast_tcptls_stream_set_timeout_disable(struct ast_tcptls_stream *stream) @@ -102,6 +104,13 @@ void ast_tcptls_stream_set_timeout_sequence(struct ast_tcptls_stream *stream, st stream->timeout = timeout; } +void ast_tcptls_stream_set_exclusive_input(struct ast_tcptls_stream *stream, int exclusive_input) +{ + ast_assert(stream != NULL); + + stream->exclusive_input = exclusive_input; +} + /*! * \internal * \brief fopencookie()/funopen() stream read function. @@ -151,6 +160,11 @@ static HOOK_T tcptls_stream_read(void *cookie, char *buf, LEN_T size) ast_debug(1, "TLS clean shutdown alert reading data\n"); return 0; case SSL_ERROR_WANT_READ: + if (!stream->exclusive_input) { + /* We cannot wait for data now. */ + errno = EAGAIN; + return -1; + } while ((ms = ast_remaining_ms(start, stream->timeout))) { res = ast_wait_for_input(stream->fd, ms); if (0 < res) { @@ -202,7 +216,8 @@ static HOOK_T tcptls_stream_read(void *cookie, char *buf, LEN_T size) for (;;) { res = read(stream->fd, buf, size); - if (0 <= res) { + if (0 <= res || !stream->exclusive_input) { + /* Got data or we cannot wait for it. */ return res; } if (errno != EINTR && errno != EAGAIN) { -- GitLab