diff options
author | des <des@FreeBSD.org> | 2002-10-27 16:11:21 +0000 |
---|---|---|
committer | des <des@FreeBSD.org> | 2002-10-27 16:11:21 +0000 |
commit | 34e6c489c762ffd7ea3491b3cf85302c64a36b97 (patch) | |
tree | eec6756c8581909e18114c1772d9c8ca0d67bbe0 | |
parent | e6f3037210bd2a8b2debfe2237120ff0c87b2566 (diff) | |
download | FreeBSD-src-34e6c489c762ffd7ea3491b3cf85302c64a36b97.zip FreeBSD-src-34e6c489c762ffd7ea3491b3cf85302c64a36b97.tar.gz |
Introduce _fetch_writev(), which is the conn_t version of writev(2). In
the SSL case, it is no different from the old _fetch_write(), but in the
non-SSL case it uses writev(2) to send the entire vector as a single
packet (provided it can fit in one packet). Implement _fetch_write()
and _fetch_putln() in terms of _fetch_writev().
This should improve performance in the non-SSL case (by reducing protocol
overhead) and solve the problem where too-smart-for-their-own-good
firewalls reject FTP packets that do not end in CRLF.
PR: bin/44123
Submitted by: fenner
-rw-r--r-- | lib/libfetch/common.c | 41 | ||||
-rw-r--r-- | lib/libfetch/common.h | 4 |
2 files changed, 38 insertions, 7 deletions
diff --git a/lib/libfetch/common.c b/lib/libfetch/common.c index 48ac5d3..ab3f4ca 100644 --- a/lib/libfetch/common.c +++ b/lib/libfetch/common.c @@ -454,6 +454,20 @@ _fetch_getln(conn_t *conn) ssize_t _fetch_write(conn_t *conn, const char *buf, size_t len) { + struct iovec iov; + + iov.iov_base = (char *)buf; + iov.iov_len = len; + return _fetch_writev(conn, &iov, 1); +} + +/* + * Write a vector to a connection w/ timeout + * Note: can modify the iovec. + */ +ssize_t +_fetch_writev(conn_t *conn, struct iovec *iov, int iovcnt) +{ struct timeval now, timeout, wait; fd_set writefds; ssize_t wlen, total; @@ -466,7 +480,7 @@ _fetch_write(conn_t *conn, const char *buf, size_t len) } total = 0; - while (len > 0) { + while (iovcnt > 0) { while (fetchTimeout && !FD_ISSET(conn->sd, &writefds)) { FD_SET(conn->sd, &writefds); gettimeofday(&now, NULL); @@ -492,10 +506,11 @@ _fetch_write(conn_t *conn, const char *buf, size_t len) errno = 0; #ifdef WITH_SSL if (conn->ssl != NULL) - wlen = SSL_write(conn->ssl, buf, len); + wlen = SSL_write(conn->ssl, + iov->iov_base, iov->iov_len); else #endif - wlen = write(conn->sd, buf, len); + wlen = writev(conn->sd, iov, iovcnt); if (wlen == 0) { /* we consider a short write a failure */ errno = EPIPE; @@ -507,9 +522,17 @@ _fetch_write(conn_t *conn, const char *buf, size_t len) continue; return (-1); } - len -= wlen; - buf += wlen; total += wlen; + while (iovcnt > 0 && wlen > iov->iov_len) { + wlen -= iov->iov_len; + iov++; + iovcnt--; + } + if (iovcnt > 0) { + iov->iov_len -= wlen; + iov->iov_base += wlen; + wlen = 0; + } } return (total); } @@ -521,10 +544,14 @@ _fetch_write(conn_t *conn, const char *buf, size_t len) int _fetch_putln(conn_t *conn, const char *str, size_t len) { + struct iovec iov[2]; DEBUG(fprintf(stderr, ">>> %s\n", str)); - if (_fetch_write(conn, str, len) == -1 || - _fetch_write(conn, ENDL, sizeof ENDL) == -1) + iov[0].iov_base = (char *)str; + iov[0].iov_len = len; + iov[1].iov_base = (char *)ENDL; + iov[1].iov_len = sizeof ENDL; + if (_fetch_writev(conn, iov, 2) == -1) return (-1); return (0); } diff --git a/lib/libfetch/common.h b/lib/libfetch/common.h index 42f68a8..4b42bf2 100644 --- a/lib/libfetch/common.h +++ b/lib/libfetch/common.h @@ -68,6 +68,9 @@ struct fetcherr { const char *string; }; +/* for _fetch_writev */ +struct iovec; + void _fetch_seterr(struct fetcherr *, int); void _fetch_syserr(void); void _fetch_info(const char *, ...); @@ -80,6 +83,7 @@ int _fetch_ssl(conn_t *, int); ssize_t _fetch_read(conn_t *, char *, size_t); int _fetch_getln(conn_t *); ssize_t _fetch_write(conn_t *, const char *, size_t); +ssize_t _fetch_writev(conn_t *, struct iovec *, int); int _fetch_putln(conn_t *, const char *, size_t); int _fetch_close(conn_t *); int _fetch_add_entry(struct url_ent **, int *, int *, |