diff options
author | Mark Michelson <mmichelson@digium.com> | 2012-10-12 16:31:01 +0000 |
---|---|---|
committer | Mark Michelson <mmichelson@digium.com> | 2012-10-12 16:31:01 +0000 |
commit | c7b23cbb0af1928014cb283c511b9dec48488163 (patch) | |
tree | b9d0286502a98f9fdffbbd94c4150f616ddef54b /main/tcptls.c | |
parent | 399428224d0a4d22b401fc228056ced705c07bdd (diff) |
Do not use a FILE handle when doing SIP TCP reads.
This is used to solve an issue where a poll on a file
descriptor does not necessarily correspond to the readiness
of a FILE handle to be read.
This change makes it so that for TCP connections, we do a
recv() on the file descriptor instead.
Because TCP does not guarantee that an entire message or even
just one single message will arrive during a read, a loop has
been introduced to ensure that we only attempt to handle a
single message at a time. The tcptls_session_instance structure
has also had an overflow buffer added to it so that if more
than one TCP message arrives in one go, there is a place to
throw the excess.
Huge thanks goes out to Walter Doekes for doing extensive review
on this change and finding edge cases where code could fail.
(closes issue ASTERISK-20212)
reported by Phil Ciccone
Review: https://reviewboard.asterisk.org/r/2123
........
Merged revisions 374905 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 374906 from http://svn.asterisk.org/svn/asterisk/branches/10
........
Merged revisions 374914 from http://svn.asterisk.org/svn/asterisk/branches/11
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@374924 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/tcptls.c')
-rw-r--r-- | main/tcptls.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/main/tcptls.c b/main/tcptls.c index 2e5cbf4c6..b52cdc491 100644 --- a/main/tcptls.c +++ b/main/tcptls.c @@ -142,6 +142,12 @@ HOOK_T ast_tcptls_server_write(struct ast_tcptls_session_instance *tcptls_sessio return write(tcptls_session->fd, buf, count); } +static void session_instance_destructor(void *obj) +{ + struct ast_tcptls_session_instance *i = obj; + ast_free(i->overflow_buf); +} + /*! \brief * creates a FILE * from the fd passed by the accept thread. * This operation is potentially expensive (certificate verification), @@ -290,7 +296,7 @@ void *ast_tcptls_server_root(void *data) } continue; } - tcptls_session = ao2_alloc(sizeof(*tcptls_session), NULL); + tcptls_session = ao2_alloc(sizeof(*tcptls_session), session_instance_destructor); if (!tcptls_session) { ast_log(LOG_WARNING, "No memory for new session: %s\n", strerror(errno)); if (close(fd)) { @@ -299,6 +305,7 @@ void *ast_tcptls_server_root(void *data) continue; } + tcptls_session->overflow_buf = ast_str_create(128); flags = fcntl(fd, F_GETFL); fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); tcptls_session->fd = fd; @@ -498,10 +505,11 @@ struct ast_tcptls_session_instance *ast_tcptls_client_create(struct ast_tcptls_s } } - if (!(tcptls_session = ao2_alloc(sizeof(*tcptls_session), NULL))) { + if (!(tcptls_session = ao2_alloc(sizeof(*tcptls_session), session_instance_destructor))) { goto error; } + tcptls_session->overflow_buf = ast_str_create(128); tcptls_session->client = 1; tcptls_session->fd = desc->accept_fd; tcptls_session->parent = desc; |