[svn-commits] rmudgett: branch 11 r420435 - in /branches/11: ./ channels/chan_sip.c
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Thu Aug 7 16:37:09 CDT 2014
Author: rmudgett
Date: Thu Aug 7 16:37:04 2014
New Revision: 420435
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=420435
Log:
chan_sip: Replace sip_tls_read() and resolve the large SDP poll issue.
Replace sip_tls_read() and sip_tcp_read() with a single function and
resolve the poll/wait issue with large SDP payloads.
ASTERISK-18345 #close
Reported by: Stephane Chazelas
Patches:
tcptls_pollv4.diff (license #5835) patch uploaded by Elazar Broad
Review: https://reviewboard.asterisk.org/r/3882/
........
Merged revisions 420434 from http://svn.asterisk.org/svn/asterisk/branches/1.8
Modified:
branches/11/ (props changed)
branches/11/channels/chan_sip.c
Propchange: branches/11/
------------------------------------------------------------------------------
Binary property 'branch-1.8-merged' - no diff available.
Modified: branches/11/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/branches/11/channels/chan_sip.c?view=diff&rev=420435&r1=420434&r2=420435
==============================================================================
--- branches/11/channels/chan_sip.c (original)
+++ branches/11/channels/chan_sip.c Thu Aug 7 16:37:04 2014
@@ -2647,156 +2647,6 @@
}
/*!
- * \brief Read a SIP request or response from a TLS connection
- *
- * Because TLS operations are hidden from view via a FILE handle, the
- * logic for reading data is a bit complex, and we have to make periodic
- * checks to be sure we aren't taking too long to perform the necessary
- * action.
- *
- * \todo XXX This should be altered in the future not to use a FILE pointer
- *
- * \param req The request structure to fill in
- * \param tcptls_session The TLS connection on which the data is being received
- * \param authenticated A flag indicating whether authentication has occurred yet.
- * This is only relevant in a server role.
- * \param start The time at which we started attempting to read data. Used in
- * determining if there has been a timeout.
- * \param me Thread info. Used as a means of determining if the session needs to be stoppped.
- * \retval -1 Failed to read data
- * \retval 0 Succeeded in reading data
- */
-static int sip_tls_read(struct sip_request *req, struct sip_request *reqcpy, struct ast_tcptls_session_instance *tcptls_session,
- int authenticated, time_t start, struct sip_threadinfo *me)
-{
- int res, content_length, after_poll = 1, need_poll = 1;
- size_t datalen = ast_str_strlen(req->data);
- char buf[1024] = "";
- int timeout = -1;
-
- /* Read in headers one line at a time */
- while (datalen < 4 || strncmp(REQ_OFFSET_TO_STR(req, data->used - 4), "\r\n\r\n", 4)) {
- if (!tcptls_session->client && !authenticated) {
- if ((timeout = sip_check_authtimeout(start)) < 0) {
- ast_debug(2, "SIP TLS server failed to determine authentication timeout\n");
- return -1;
- }
-
- if (timeout == 0) {
- ast_debug(2, "SIP TLS server timed out\n");
- return -1;
- }
- } else {
- timeout = -1;
- }
-
- /* special polling behavior is required for TLS
- * sockets because of the buffering done in the
- * TLS layer */
- if (need_poll) {
- need_poll = 0;
- after_poll = 1;
- res = ast_wait_for_input(tcptls_session->fd, timeout);
- if (res < 0) {
- ast_debug(2, "SIP TLS server :: ast_wait_for_input returned %d\n", res);
- return -1;
- } else if (res == 0) {
- /* timeout */
- ast_debug(2, "SIP TLS server timed out\n");
- return -1;
- }
- }
-
- ao2_lock(tcptls_session);
- if (!fgets(buf, sizeof(buf), tcptls_session->f)) {
- ao2_unlock(tcptls_session);
- if (after_poll) {
- return -1;
- } else {
- need_poll = 1;
- continue;
- }
- }
- ao2_unlock(tcptls_session);
- after_poll = 0;
- if (me->stop) {
- return -1;
- }
- ast_str_append(&req->data, 0, "%s", buf);
-
- datalen = ast_str_strlen(req->data);
- if (datalen > SIP_MAX_PACKET_SIZE) {
- ast_log(LOG_WARNING, "Rejecting TLS packet from '%s' because way too large: %zu\n",
- ast_sockaddr_stringify(&tcptls_session->remote_address), datalen);
- return -1;
- }
- }
- copy_request(reqcpy, req);
- parse_request(reqcpy);
- /* In order to know how much to read, we need the content-length header */
- if (sscanf(sip_get_header(reqcpy, "Content-Length"), "%30d", &content_length)) {
- while (content_length > 0) {
- size_t bytes_read;
- if (!tcptls_session->client && !authenticated) {
- if ((timeout = sip_check_authtimeout(start)) < 0) {
- return -1;
- }
-
- if (timeout == 0) {
- ast_debug(2, "SIP TLS server timed out\n");
- return -1;
- }
- } else {
- timeout = -1;
- }
-
- if (need_poll) {
- need_poll = 0;
- after_poll = 1;
- res = ast_wait_for_input(tcptls_session->fd, timeout);
- if (res < 0) {
- ast_debug(2, "SIP TLS server :: ast_wait_for_input returned %d\n", res);
- return -1;
- } else if (res == 0) {
- /* timeout */
- ast_debug(2, "SIP TLS server timed out\n");
- return -1;
- }
- }
-
- ao2_lock(tcptls_session);
- if (!(bytes_read = fread(buf, 1, MIN(sizeof(buf) - 1, content_length), tcptls_session->f))) {
- ao2_unlock(tcptls_session);
- if (after_poll) {
- return -1;
- } else {
- need_poll = 1;
- continue;
- }
- }
- buf[bytes_read] = '\0';
- ao2_unlock(tcptls_session);
- after_poll = 0;
- if (me->stop) {
- return -1;
- }
- content_length -= strlen(buf);
- ast_str_append(&req->data, 0, "%s", buf);
-
- datalen = ast_str_strlen(req->data);
- if (datalen > SIP_MAX_PACKET_SIZE) {
- ast_log(LOG_WARNING, "Rejecting TLS packet from '%s' because way too large: %zu\n",
- ast_sockaddr_stringify(&tcptls_session->remote_address), datalen);
- return -1;
- }
- }
- }
- /*! \todo XXX If there's no Content-Length or if the content-length and what
- we receive is not the same - we should generate an error */
- return 0;
-}
-
-/*!
* \brief Indication of a TCP message's integrity
*/
enum message_integrity {
@@ -2949,14 +2799,14 @@
}
/*!
- * \brief Read SIP request or response from a TCP connection
+ * \brief Read SIP request or response from a TCP/TLS connection
*
* \param req The request structure to be filled in
- * \param tcptls_session The TCP connection from which to read
+ * \param tcptls_session The TCP/TLS connection from which to read
* \retval -1 Failed to read data
* \retval 0 Successfully read data
*/
-static int sip_tcp_read(struct sip_request *req, struct ast_tcptls_session_instance *tcptls_session,
+static int sip_tcptls_read(struct sip_request *req, struct ast_tcptls_session_instance *tcptls_session,
int authenticated, time_t start)
{
enum message_integrity message_integrity = MESSAGE_FRAGMENT;
@@ -2974,7 +2824,7 @@
}
if (timeout == 0) {
- ast_debug(2, "SIP TCP server timed out\n");
+ ast_debug(2, "SIP TCP/TLS server timed out\n");
return -1;
}
} else {
@@ -2982,19 +2832,22 @@
}
res = ast_wait_for_input(tcptls_session->fd, timeout);
if (res < 0) {
- ast_debug(2, "SIP TCP server :: ast_wait_for_input returned %d\n", res);
+ ast_debug(2, "SIP TCP/TLS server :: ast_wait_for_input returned %d\n", res);
return -1;
} else if (res == 0) {
- ast_debug(2, "SIP TCP server timed out\n");
+ ast_debug(2, "SIP TCP/TLS server timed out\n");
return -1;
}
- res = recv(tcptls_session->fd, readbuf, sizeof(readbuf) - 1, 0);
+ res = ast_tcptls_server_read(tcptls_session, readbuf, sizeof(readbuf) - 1);
if (res < 0) {
- ast_debug(2, "SIP TCP server error when receiving data\n");
+ if (errno == EAGAIN || errno == EINTR) {
+ continue;
+ }
+ ast_debug(2, "SIP TCP/TLS server error when receiving data\n");
return -1;
} else if (res == 0) {
- ast_debug(2, "SIP TCP server has shut down\n");
+ ast_debug(2, "SIP TCP/TLS server has shut down\n");
return -1;
}
readbuf[res] = '\0';
@@ -3003,10 +2856,10 @@
ast_str_append(&req->data, 0, "%s", ast_str_buffer(tcptls_session->overflow_buf));
ast_str_reset(tcptls_session->overflow_buf);
}
-
+
datalen = ast_str_strlen(req->data);
if (datalen > SIP_MAX_PACKET_SIZE) {
- ast_log(LOG_WARNING, "Rejecting TCP packet from '%s' because way too large: %zu\n",
+ ast_log(LOG_WARNING, "Rejecting TCP/TLS packet from '%s' because way too large: %zu\n",
ast_sockaddr_stringify(&tcptls_session->remote_address), datalen);
return -1;
}
@@ -3172,12 +3025,8 @@
req.socket.port = htons(ourport_tcp);
}
req.socket.fd = tcptls_session->fd;
- if (tcptls_session->ssl) {
- res = sip_tls_read(&req, &reqcpy, tcptls_session, authenticated, start, me);
- } else {
- res = sip_tcp_read(&req, tcptls_session, authenticated, start);
- }
-
+
+ res = sip_tcptls_read(&req, tcptls_session, authenticated, start);
if (res < 0) {
goto cleanup;
}
More information about the svn-commits
mailing list