From owner-svn-src-stable@FreeBSD.ORG Wed May 11 09:46:36 2011 Return-Path: Delivered-To: svn-src-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 88015106568B; Wed, 11 May 2011 09:46:36 +0000 (UTC) (envelope-from des@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 76AAA8FC12; Wed, 11 May 2011 09:46:36 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p4B9ka5D083674; Wed, 11 May 2011 09:46:36 GMT (envelope-from des@svn.freebsd.org) Received: (from des@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id p4B9kaTL083669; Wed, 11 May 2011 09:46:36 GMT (envelope-from des@svn.freebsd.org) Message-Id: <201105110946.p4B9kaTL083669@svn.freebsd.org> From: Dag-Erling Smorgrav Date: Wed, 11 May 2011 09:46:36 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r221765 - stable/7/lib/libfetch X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 11 May 2011 09:46:36 -0000 Author: des Date: Wed May 11 09:46:36 2011 New Revision: 221765 URL: http://svn.freebsd.org/changeset/base/221765 Log: Sync with head: proxy authentication, SSL hang, cached connection crash. Modified: stable/7/lib/libfetch/Makefile stable/7/lib/libfetch/common.c stable/7/lib/libfetch/ftp.c stable/7/lib/libfetch/http.c Directory Properties: stable/7/lib/libfetch/ (props changed) Modified: stable/7/lib/libfetch/Makefile ============================================================================== --- stable/7/lib/libfetch/Makefile Wed May 11 09:42:40 2011 (r221764) +++ stable/7/lib/libfetch/Makefile Wed May 11 09:46:36 2011 (r221765) @@ -28,7 +28,7 @@ CFLAGS+= -DFTP_COMBINE_CWDS CSTD?= c99 WARNS?= 2 -SHLIB_MAJOR= 5 +SHLIB_MAJOR= 6 ftperr.h: ftp.errors ${.CURDIR}/Makefile @echo "static struct fetcherr ftp_errlist[] = {" > ${.TARGET} Modified: stable/7/lib/libfetch/common.c ============================================================================== --- stable/7/lib/libfetch/common.c Wed May 11 09:42:40 2011 (r221764) +++ stable/7/lib/libfetch/common.c Wed May 11 09:46:36 2011 (r221765) @@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -295,7 +296,8 @@ fetch_connect(const char *host, int port close(sd); continue; } - if (connect(sd, res->ai_addr, res->ai_addrlen) == 0) + if (connect(sd, res->ai_addr, res->ai_addrlen) == 0 && + fcntl(sd, F_SETFL, O_NONBLOCK) == 0) break; close(sd); } @@ -319,8 +321,9 @@ fetch_connect(const char *host, int port int fetch_ssl(conn_t *conn, int verbose) { - #ifdef WITH_SSL + int ret, ssl_err; + /* Init the SSL library and context */ if (!SSL_library_init()){ fprintf(stderr, "SSL library init failed\n"); @@ -339,9 +342,13 @@ fetch_ssl(conn_t *conn, int verbose) return (-1); } SSL_set_fd(conn->ssl, conn->sd); - if (SSL_connect(conn->ssl) == -1){ - ERR_print_errors_fp(stderr); - return (-1); + while ((ret = SSL_connect(conn->ssl)) == -1) { + ssl_err = SSL_get_error(conn->ssl, ret); + if (ssl_err != SSL_ERROR_WANT_READ && + ssl_err != SSL_ERROR_WANT_WRITE) { + ERR_print_errors_fp(stderr); + return (-1); + } } if (verbose) { @@ -370,6 +377,46 @@ fetch_ssl(conn_t *conn, int verbose) #endif } +#define FETCH_READ_WAIT -2 +#define FETCH_READ_ERROR -1 +#define FETCH_READ_DONE 0 + +#ifdef WITH_SSL +static ssize_t +fetch_ssl_read(SSL *ssl, char *buf, size_t len) +{ + ssize_t rlen; + int ssl_err; + + rlen = SSL_read(ssl, buf, len); + if (rlen < 0) { + ssl_err = SSL_get_error(ssl, rlen); + if (ssl_err == SSL_ERROR_WANT_READ || + ssl_err == SSL_ERROR_WANT_WRITE) { + return (FETCH_READ_WAIT); + } else { + ERR_print_errors_fp(stderr); + return (FETCH_READ_ERROR); + } + } + return (rlen); +} +#endif + +static ssize_t +fetch_socket_read(int sd, char *buf, size_t len) +{ + ssize_t rlen; + + rlen = read(sd, buf, len); + if (rlen < 0) { + if (errno == EAGAIN || (errno == EINTR && fetchRestartCalls)) + return (FETCH_READ_WAIT); + else + return (FETCH_READ_ERROR); + } + return (rlen); +} /* * Read a character from a connection w/ timeout @@ -390,6 +437,43 @@ fetch_read(conn_t *conn, char *buf, size total = 0; while (len > 0) { + /* + * The socket is non-blocking. Instead of the canonical + * select() -> read(), we do the following: + * + * 1) call read() or SSL_read(). + * 2) if an error occurred, return -1. + * 3) if we received data but we still expect more, + * update our counters and loop. + * 4) if read() or SSL_read() signaled EOF, return. + * 5) if we did not receive any data but we're not at EOF, + * call select(). + * + * In the SSL case, this is necessary because if we + * receive a close notification, we have to call + * SSL_read() one additional time after we've read + * everything we received. + * + * In the non-SSL case, it may improve performance (very + * slightly) when reading small amounts of data. + */ +#ifdef WITH_SSL + if (conn->ssl != NULL) + rlen = fetch_ssl_read(conn->ssl, buf, len); + else +#endif + rlen = fetch_socket_read(conn->sd, buf, len); + if (rlen == 0) { + break; + } else if (rlen > 0) { + len -= rlen; + buf += rlen; + total += rlen; + continue; + } else if (rlen == FETCH_READ_ERROR) { + return (-1); + } + // assert(rlen == FETCH_READ_WAIT); while (fetchTimeout && !FD_ISSET(conn->sd, &readfds)) { FD_SET(conn->sd, &readfds); gettimeofday(&now, NULL); @@ -413,22 +497,6 @@ fetch_read(conn_t *conn, char *buf, size return (-1); } } -#ifdef WITH_SSL - if (conn->ssl != NULL) - rlen = SSL_read(conn->ssl, buf, len); - else -#endif - rlen = read(conn->sd, buf, len); - if (rlen == 0) - break; - if (rlen < 0) { - if (errno == EINTR && fetchRestartCalls) - continue; - return (-1); - } - len -= rlen; - buf += rlen; - total += rlen; } return (total); } @@ -548,6 +616,7 @@ fetch_writev(conn_t *conn, struct iovec wlen = writev(conn->sd, iov, iovcnt); if (wlen == 0) { /* we consider a short write a failure */ + /* XXX perhaps we shouldn't in the SSL case */ errno = EPIPE; fetch_syserr(); return (-1); Modified: stable/7/lib/libfetch/ftp.c ============================================================================== --- stable/7/lib/libfetch/ftp.c Wed May 11 09:42:40 2011 (r221764) +++ stable/7/lib/libfetch/ftp.c Wed May 11 09:46:36 2011 (r221765) @@ -1132,6 +1132,7 @@ ftp_request(struct url *url, const char /* just a stat */ if (strcmp(op, "STAT") == 0) { + --conn->ref; ftp_disconnect(conn); return (FILE *)1; /* bogus return value */ } Modified: stable/7/lib/libfetch/http.c ============================================================================== --- stable/7/lib/libfetch/http.c Wed May 11 09:42:40 2011 (r221764) +++ stable/7/lib/libfetch/http.c Wed May 11 09:46:36 2011 (r221765) @@ -1786,12 +1786,14 @@ http_request(struct url *URL, const char case hdr_www_authenticate: if (conn->err != HTTP_NEED_AUTH) break; - http_parse_authenticate(p, &server_challenges); + if (http_parse_authenticate(p, &server_challenges) == 0) + ++n; break; case hdr_proxy_authenticate: if (conn->err != HTTP_NEED_PROXY_AUTH) break; - http_parse_authenticate(p, &proxy_challenges); + if (http_parse_authenticate(p, &proxy_challenges) == 0) + ++n; break; case hdr_end: /* fall through */