]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
This commit modifies the way polling is done on TLS sockets.
authorMatthew Nicholson <mnicholson@digium.com>
Fri, 20 May 2011 18:45:59 +0000 (18:45 +0000)
committerMatthew Nicholson <mnicholson@digium.com>
Fri, 20 May 2011 18:45:59 +0000 (18:45 +0000)
Because of the buffering the TLS layer does, polling is unreliable. If poll is
called while there is data waiting to be read in the TLS layer but not at the
network layer, the messaging processing engine will not proceed until something
else writes data to the socket, which may not occur. This change modifies the
logic around TLS sockets to only poll after a failed read on a non-blocking
socket. This way we know that there is no data waiting to be read from the
buffering layer.

(closes issue #19182)
Reported by: st
Patches:
      ssl-poll-fix3.diff uploaded by mnicholson (license 96)
Tested by: mnicholson

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.2@320179 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_sip.c

index 1ac756a400a989a435d9519833467da0f14a8ad8..1865c94a089252e456e8e891c7882299d48ae867 100644 (file)
@@ -2954,7 +2954,7 @@ static int sip_check_authtimeout(time_t start)
 */
 static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct ast_tcptls_session_instance *tcptls_session) 
 {
-       int res, cl, timeout = -1, authenticated = 0, flags;
+       int res, cl, timeout = -1, authenticated = 0, flags, after_poll = 0, need_poll = 1;
        time_t start;
        struct sip_request req = { 0, } , reqcpy = { 0, };
        struct sip_threadinfo *me = NULL;
@@ -3065,6 +3065,7 @@ static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct ast_tcptls_sessi
                /* handle the socket event, check for both reads from the socket fd,
                 * and writes from alert_pipe fd */
                if (fds[0].revents) { /* there is data on the socket to be read */
+                       after_poll = 1;
 
                        fds[0].revents = 0;
 
@@ -3105,22 +3106,32 @@ static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct ast_tcptls_sessi
                                        timeout = -1;
                                }
 
-                               res = ast_wait_for_input(tcptls_session->fd, timeout);
-                               if (res < 0) {
-                                       ast_debug(2, "SIP %s server :: ast_wait_for_input returned %d\n", tcptls_session->ssl ? "SSL": "TCP", res);
-                                       goto cleanup;
-                               } else if (res == 0) {
-                                       /* timeout */
-                                       ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "SSL": "TCP");
-                                       goto cleanup;
+                               if (!tcptls_session->ssl || need_poll) {
+                                       need_poll = 0;
+                                       after_poll = 1;
+                                       res = ast_wait_for_input(tcptls_session->fd, timeout);
+                                       if (res < 0) {
+                                               ast_debug(2, "SIP %s server :: ast_wait_for_input returned %d\n", tcptls_session->ssl ? "SSL": "TCP", res);
+                                               goto cleanup;
+                                       } else if (res == 0) {
+                                               /* timeout */
+                                               ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "SSL": "TCP");
+                                               goto cleanup;
+                                       }
                                }
 
                                ast_mutex_lock(&tcptls_session->lock);
                                if (!fgets(buf, sizeof(buf), tcptls_session->f)) {
                                        ast_mutex_unlock(&tcptls_session->lock);
-                                       goto cleanup;
+                                       if (after_poll) {
+                                               goto cleanup;
+                                       } else {
+                                               need_poll = 1;
+                                               continue;
+                                       }
                                }
                                ast_mutex_unlock(&tcptls_session->lock);
+                               after_poll = 0;
                                if (me->stop)
                                         goto cleanup;
                                ast_str_append(&req.data, 0, "%s", buf);
@@ -3138,30 +3149,38 @@ static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct ast_tcptls_sessi
                                                }
 
                                                if (timeout == 0) {
-                                                       ast_debug(2, "SIP %s server timed out", tcptls_session->ssl ? "SSL": "TCP");
+                                                       ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "SSL": "TCP");
                                                        goto cleanup;
                                                }
                                        } else {
                                                timeout = -1;
                                        }
 
-                                       res = ast_wait_for_input(tcptls_session->fd, timeout);
-                                       if (res < 0) {
-                                               ast_debug(2, "SIP %s server :: ast_wait_for_input returned %d\n", tcptls_session->ssl ? "SSL": "TCP", res);
-                                               goto cleanup;
-                                       } else if (res == 0) {
-                                               /* timeout */
-                                               ast_debug(2, "SIP %s server timed out", tcptls_session->ssl ? "SSL": "TCP");
-                                               goto cleanup;
+                                       if (!tcptls_session->ssl || need_poll) {
+                                               res = ast_wait_for_input(tcptls_session->fd, timeout);
+                                               if (res < 0) {
+                                                       ast_debug(2, "SIP %s server :: ast_wait_for_input returned %d\n", tcptls_session->ssl ? "SSL": "TCP", res);
+                                                       goto cleanup;
+                                               } else if (res == 0) {
+                                                       /* timeout */
+                                                       ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "SSL": "TCP");
+                                                       goto cleanup;
+                                               }
                                        }
 
                                        ast_mutex_lock(&tcptls_session->lock);
                                        if (!(bytes_read = fread(buf, 1, MIN(sizeof(buf) - 1, cl), tcptls_session->f))) {
                                                ast_mutex_unlock(&tcptls_session->lock);
-                                               goto cleanup;
+                                               if (after_poll) {
+                                                       goto cleanup;
+                                               } else {
+                                                       need_poll = 1;
+                                                       continue;
+                                               }
                                        }
                                        buf[bytes_read] = '\0';
                                        ast_mutex_unlock(&tcptls_session->lock);
+                                       after_poll = 0;
                                        if (me->stop)
                                                goto cleanup;
                                        cl -= strlen(buf);