mirror of
https://github.com/asterisk/asterisk.git
synced 2025-11-20 08:40:16 +00:00
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 git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/11@374914 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -155,6 +155,12 @@ struct ast_tcptls_session_instance {
|
|||||||
int client;
|
int client;
|
||||||
struct ast_sockaddr remote_address;
|
struct ast_sockaddr remote_address;
|
||||||
struct ast_tcptls_session_args *parent;
|
struct ast_tcptls_session_args *parent;
|
||||||
|
/* Sometimes, when an entity reads TCP data, multiple
|
||||||
|
* logical messages might be read at the same time. In such
|
||||||
|
* a circumstance, there needs to be a place to stash the
|
||||||
|
* extra data.
|
||||||
|
*/
|
||||||
|
struct ast_str *overflow_buf;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(HAVE_FUNOPEN)
|
#if defined(HAVE_FUNOPEN)
|
||||||
|
|||||||
@@ -142,6 +142,12 @@ HOOK_T ast_tcptls_server_write(struct ast_tcptls_session_instance *tcptls_sessio
|
|||||||
return write(tcptls_session->fd, buf, count);
|
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
|
/*! \brief
|
||||||
* creates a FILE * from the fd passed by the accept thread.
|
* creates a FILE * from the fd passed by the accept thread.
|
||||||
* This operation is potentially expensive (certificate verification),
|
* This operation is potentially expensive (certificate verification),
|
||||||
@@ -290,7 +296,7 @@ void *ast_tcptls_server_root(void *data)
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
tcptls_session = ao2_alloc(sizeof(*tcptls_session), NULL);
|
tcptls_session = ao2_alloc(sizeof(*tcptls_session), session_instance_destructor);
|
||||||
if (!tcptls_session) {
|
if (!tcptls_session) {
|
||||||
ast_log(LOG_WARNING, "No memory for new session: %s\n", strerror(errno));
|
ast_log(LOG_WARNING, "No memory for new session: %s\n", strerror(errno));
|
||||||
if (close(fd)) {
|
if (close(fd)) {
|
||||||
@@ -299,6 +305,7 @@ void *ast_tcptls_server_root(void *data)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tcptls_session->overflow_buf = ast_str_create(128);
|
||||||
flags = fcntl(fd, F_GETFL);
|
flags = fcntl(fd, F_GETFL);
|
||||||
fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
|
fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
|
||||||
tcptls_session->fd = fd;
|
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;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tcptls_session->overflow_buf = ast_str_create(128);
|
||||||
tcptls_session->client = 1;
|
tcptls_session->client = 1;
|
||||||
tcptls_session->fd = desc->accept_fd;
|
tcptls_session->fd = desc->accept_fd;
|
||||||
tcptls_session->parent = desc;
|
tcptls_session->parent = desc;
|
||||||
|
|||||||
Reference in New Issue
Block a user