From: David Woodhouse Date: Sat, 12 May 2012 20:12:13 +0000 (-0700) Subject: Handle cancellation in openconnect_SSL_gets() X-Git-Tag: v3.19~29 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=409dfab178f69a123afcbf762e5657a1c744e8f1;p=platform%2Fupstream%2Fopenconnect.git Handle cancellation in openconnect_SSL_gets() Signed-off-by: David Woodhouse --- diff --git a/cstp.c b/cstp.c index 0408dc0..98c5e55 100644 --- a/cstp.c +++ b/cstp.c @@ -128,8 +128,9 @@ static int start_cstp_connection(struct openconnect_info *vpninfo) openconnect_SSL_printf(vpninfo, "\r\nX-DTLS-CipherSuite: %s\r\n\r\n", vpninfo->dtls_ciphers?:"AES256-SHA:AES128-SHA:DES-CBC3-SHA:DES-CBC-SHA"); - fcntl(vpninfo->ssl_fd, F_SETFL, fcntl(vpninfo->ssl_fd, F_GETFL) & ~O_NONBLOCK); - if (openconnect_SSL_gets(vpninfo, buf, 65536) < 0) { + if ((i = openconnect_SSL_gets(vpninfo, buf, 65536) < 0)) { + if (i == -EINTR) + return i; vpn_progress(vpninfo, PRG_ERR, _("Error fetching HTTPS response\n")); if (!retried) { @@ -177,7 +178,12 @@ static int start_cstp_connection(struct openconnect_info *vpninfo) while ((i = openconnect_SSL_gets(vpninfo, buf, sizeof(buf)))) { struct vpn_option *new_option; - char *colon = strchr(buf, ':'); + char *colon; + + if (i < 0) + return i; + + colon = strchr(buf, ':'); if (!colon) continue; @@ -356,7 +362,6 @@ static int start_cstp_connection(struct openconnect_info *vpninfo) BIO_set_nbio(SSL_get_rbio(vpninfo->https_ssl), 1); BIO_set_nbio(SSL_get_wbio(vpninfo->https_ssl), 1); - fcntl(vpninfo->ssl_fd, F_SETFL, fcntl(vpninfo->ssl_fd, F_GETFL) | O_NONBLOCK); if (vpninfo->select_nfds <= vpninfo->ssl_fd) vpninfo->select_nfds = vpninfo->ssl_fd + 1; diff --git a/ssl.c b/ssl.c index 677d071..58c233f 100644 --- a/ssl.c +++ b/ssl.c @@ -138,25 +138,55 @@ int openconnect_SSL_gets(struct openconnect_info *vpninfo, char *buf, size_t len if (len < 2) return -EINVAL; - while ( (ret = SSL_read(vpninfo->https_ssl, buf + i, 1)) == 1) { - if (buf[i] == '\n') { - buf[i] = 0; - if (i && buf[i-1] == '\r') { - buf[i-1] = 0; - i--; + while (1) { + ret = SSL_read(vpninfo->https_ssl, buf + i, 1); + if (ret == 1) { + if (buf[i] == '\n') { + buf[i] = 0; + if (i && buf[i-1] == '\r') { + buf[i-1] = 0; + i--; + } + return i; } - return i; - } - i++; + i++; - if (i >= len - 1) { - buf[i] = 0; - return i; + if (i >= len - 1) { + buf[i] = 0; + return i; + } + } else { + fd_set rd_set, wr_set; + int maxfd = vpninfo->ssl_fd; + + FD_ZERO(&rd_set); + FD_ZERO(&wr_set); + + ret = SSL_get_error(vpninfo->https_ssl, ret); + if (ret == SSL_ERROR_WANT_READ) + FD_SET(vpninfo->ssl_fd, &rd_set); + else if (ret == SSL_ERROR_WANT_WRITE) + FD_SET(vpninfo->ssl_fd, &wr_set); + else { + vpn_progress(vpninfo, PRG_ERR, _("Failed to read from SSL socket\n")); + report_ssl_errors(vpninfo); + ret = -EIO; + break; + } + if (vpninfo->cancel_fd != -1) { + FD_SET(vpninfo->cancel_fd, &rd_set); + if (vpninfo->cancel_fd > vpninfo->ssl_fd) + maxfd = vpninfo->cancel_fd; + } + select(maxfd + 1, &rd_set, &wr_set, NULL, NULL); + if (vpninfo->cancel_fd != -1 && + FD_ISSET(vpninfo->cancel_fd, &rd_set)) { + vpn_progress(vpninfo, PRG_ERR, _("SSL read cancelled\n")); + ret = -EINTR; + break; + } } } - if (ret == 0) { - ret = -SSL_get_error(vpninfo->https_ssl, ret); - } buf[i] = 0; return i ?: ret; }