svn commit: r262560 - stable/10/lib/libfetch

Dag-Erling Smørgrav des at FreeBSD.org
Thu Feb 27 13:27:05 UTC 2014


Author: des
Date: Thu Feb 27 13:27:04 2014
New Revision: 262560
URL: http://svnweb.freebsd.org/changeset/base/262560

Log:
  MFH (r260904): fix format string
  MFH (r261230, r261263): fix buffering issues
  MFH (r261284): bump copyright

Modified:
  stable/10/lib/libfetch/common.c
  stable/10/lib/libfetch/common.h
  stable/10/lib/libfetch/http.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/lib/libfetch/common.c
==============================================================================
--- stable/10/lib/libfetch/common.c	Thu Feb 27 13:26:41 2014	(r262559)
+++ stable/10/lib/libfetch/common.c	Thu Feb 27 13:27:04 2014	(r262560)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 1998-2011 Dag-Erling Smørgrav
+ * Copyright (c) 1998-2014 Dag-Erling Smørgrav
  * Copyright (c) 2013 Michael Gmelin <freebsd at grem.de>
  * All rights reserved.
  *
@@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
 #include <errno.h>
 #include <fcntl.h>
 #include <netdb.h>
+#include <poll.h>
 #include <pwd.h>
 #include <stdarg.h>
 #include <stdlib.h>
@@ -641,7 +642,7 @@ fetch_ssl_verify_hname(X509 *cert, const
 	struct addrinfo *ip;
 	STACK_OF(GENERAL_NAME) *altnames;
 	X509_NAME *subject;
-	int ret;	
+	int ret;
 
 	ret = 0;
 	ip = fetch_ssl_get_numeric_addrinfo(host, strlen(host));
@@ -679,7 +680,7 @@ fetch_ssl_setup_transport_layer(SSL_CTX 
 	if (getenv("SSL_NO_TLS1") != NULL)
 		ssl_ctx_options |= SSL_OP_NO_TLSv1;
 	if (verbose)
-		fetch_info("SSL options: %x", ssl_ctx_options);
+		fetch_info("SSL options: %lx", ssl_ctx_options);
 	SSL_CTX_set_options(ctx, ssl_ctx_options);
 }
 
@@ -913,33 +914,6 @@ fetch_ssl_read(SSL *ssl, char *buf, size
 }
 #endif
 
-/*
- * Cache some data that was read from a socket but cannot be immediately
- * returned because of an interrupted system call.
- */
-static int
-fetch_cache_data(conn_t *conn, char *src, size_t nbytes)
-{
-	char *tmp;
-
-	if (conn->cache.size < nbytes) {
-		tmp = realloc(conn->cache.buf, nbytes);
-		if (tmp == NULL) {
-			fetch_syserr();
-			return (-1);
-		}
-		conn->cache.buf = tmp;
-		conn->cache.size = nbytes;
-	}
-
-	memcpy(conn->cache.buf, src, nbytes);
-	conn->cache.len = nbytes;
-	conn->cache.pos = 0;
-
-	return (0);
-}
-
-
 static ssize_t
 fetch_socket_read(int sd, char *buf, size_t len)
 {
@@ -962,46 +936,31 @@ ssize_t
 fetch_read(conn_t *conn, char *buf, size_t len)
 {
 	struct timeval now, timeout, delta;
-	fd_set readfds;
-	ssize_t rlen, total;
-	char *start;
+	struct pollfd pfd;
+	ssize_t rlen;
+	int deltams;
 
 	if (fetchTimeout > 0) {
 		gettimeofday(&timeout, NULL);
 		timeout.tv_sec += fetchTimeout;
 	}
 
-	total = 0;
-	start = buf;
-
-	if (conn->cache.len > 0) {
-		/*
-		 * The last invocation of fetch_read was interrupted by a
-		 * signal after some data had been read from the socket. Copy
-		 * the cached data into the supplied buffer before trying to
-		 * read from the socket again.
-		 */
-		total = (conn->cache.len < len) ? conn->cache.len : len;
-		memcpy(buf, conn->cache.buf, total);
-
-		conn->cache.len -= total;
-		conn->cache.pos += total;
-		len -= total;
-		buf += total;
-	}
+	deltams = INFTIM;
+	memset(&pfd, 0, sizeof pfd);
+	pfd.fd = conn->sd;
+	pfd.events = POLLIN | POLLERR;
 
-	while (len > 0) {
+	for (;;) {
 		/*
 		 * The socket is non-blocking.  Instead of the canonical
-		 * select() -> read(), we do the following:
+		 * poll() -> 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.
+		 * 2) if we received some data, return it.
+		 * 3) if an error occurred, return -1.
 		 * 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().
+		 *    call poll().
 		 *
 		 * In the SSL case, this is necessary because if we
 		 * receive a close notification, we have to call
@@ -1017,46 +976,34 @@ fetch_read(conn_t *conn, char *buf, size
 		else
 #endif
 			rlen = fetch_socket_read(conn->sd, buf, len);
-		if (rlen == 0) {
+		if (rlen >= 0) {
 			break;
-		} else if (rlen > 0) {
-			len -= rlen;
-			buf += rlen;
-			total += rlen;
-			continue;
 		} else if (rlen == FETCH_READ_ERROR) {
-			if (errno == EINTR)
-				fetch_cache_data(conn, start, total);
+			fetch_syserr();
 			return (-1);
 		}
 		// assert(rlen == FETCH_READ_WAIT);
-		FD_ZERO(&readfds);
-		while (!FD_ISSET(conn->sd, &readfds)) {
-			FD_SET(conn->sd, &readfds);
-			if (fetchTimeout > 0) {
-				gettimeofday(&now, NULL);
-				if (!timercmp(&timeout, &now, >)) {
-					errno = ETIMEDOUT;
-					fetch_syserr();
-					return (-1);
-				}
-				timersub(&timeout, &now, &delta);
-			}
-			errno = 0;
-			if (select(conn->sd + 1, &readfds, NULL, NULL,
-				fetchTimeout > 0 ? &delta : NULL) < 0) {
-				if (errno == EINTR) {
-					if (fetchRestartCalls)
-						continue;
-					/* Save anything that was read. */
-					fetch_cache_data(conn, start, total);
-				}
+		if (fetchTimeout > 0) {
+			gettimeofday(&now, NULL);
+			if (!timercmp(&timeout, &now, >)) {
+				errno = ETIMEDOUT;
 				fetch_syserr();
 				return (-1);
 			}
+			timersub(&timeout, &now, &delta);
+			deltams = delta.tv_sec * 1000 +
+			    delta.tv_usec / 1000;;
+		}
+		errno = 0;
+		pfd.revents = 0;
+		if (poll(&pfd, 1, deltams) < 0) {
+			if (errno == EINTR && fetchRestartCalls)
+				continue;
+			fetch_syserr();
+			return (-1);
 		}
 	}
-	return (total);
+	return (rlen);
 }
 
 
@@ -1130,35 +1077,33 @@ ssize_t
 fetch_writev(conn_t *conn, struct iovec *iov, int iovcnt)
 {
 	struct timeval now, timeout, delta;
-	fd_set writefds;
+	struct pollfd pfd;
 	ssize_t wlen, total;
-	int r;
+	int deltams;
 
+	memset(&pfd, 0, sizeof pfd);
 	if (fetchTimeout) {
-		FD_ZERO(&writefds);
+		pfd.fd = conn->sd;
+		pfd.events = POLLOUT | POLLERR;
 		gettimeofday(&timeout, NULL);
 		timeout.tv_sec += fetchTimeout;
 	}
 
 	total = 0;
 	while (iovcnt > 0) {
-		while (fetchTimeout && !FD_ISSET(conn->sd, &writefds)) {
-			FD_SET(conn->sd, &writefds);
+		while (fetchTimeout && pfd.revents == 0) {
 			gettimeofday(&now, NULL);
-			delta.tv_sec = timeout.tv_sec - now.tv_sec;
-			delta.tv_usec = timeout.tv_usec - now.tv_usec;
-			if (delta.tv_usec < 0) {
-				delta.tv_usec += 1000000;
-				delta.tv_sec--;
-			}
-			if (delta.tv_sec < 0) {
+			if (!timercmp(&timeout, &now, >)) {
 				errno = ETIMEDOUT;
 				fetch_syserr();
 				return (-1);
 			}
+			timersub(&timeout, &now, &delta);
+			deltams = delta.tv_sec * 1000 +
+			    delta.tv_usec / 1000;
 			errno = 0;
-			r = select(conn->sd + 1, NULL, &writefds, NULL, &delta);
-			if (r == -1) {
+			pfd.revents = 0;
+			if (poll(&pfd, 1, deltams) < 0) {
 				if (errno == EINTR && fetchRestartCalls)
 					continue;
 				return (-1);
@@ -1250,7 +1195,6 @@ fetch_close(conn_t *conn)
 	}
 #endif
 	ret = close(conn->sd);
-	free(conn->cache.buf);
 	free(conn->buf);
 	free(conn);
 	return (ret);

Modified: stable/10/lib/libfetch/common.h
==============================================================================
--- stable/10/lib/libfetch/common.h	Thu Feb 27 13:26:41 2014	(r262559)
+++ stable/10/lib/libfetch/common.h	Thu Feb 27 13:27:04 2014	(r262560)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 1998-2011 Dag-Erling Smørgrav
+ * Copyright (c) 1998-2014 Dag-Erling Smørgrav
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -52,13 +52,6 @@ struct fetchconn {
 	size_t		 bufsize;	/* buffer size */
 	size_t		 buflen;	/* length of buffer contents */
 	int		 err;		/* last protocol reply code */
-	struct {			/* data cached after an interrupted
-					   read */
-		char	*buf;
-		size_t	 size;
-		size_t	 pos;
-		size_t	 len;
-	} cache;
 #ifdef WITH_SSL
 	SSL		*ssl;		/* SSL handle */
 	SSL_CTX		*ssl_ctx;	/* SSL context */

Modified: stable/10/lib/libfetch/http.c
==============================================================================
--- stable/10/lib/libfetch/http.c	Thu Feb 27 13:26:41 2014	(r262559)
+++ stable/10/lib/libfetch/http.c	Thu Feb 27 13:27:04 2014	(r262560)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2000-2013 Dag-Erling Smørgrav
+ * Copyright (c) 2000-2014 Dag-Erling Smørgrav
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -204,10 +204,11 @@ http_growbuf(struct httpio *io, size_t l
 /*
  * Fill the input buffer, do chunk decoding on the fly
  */
-static int
+static ssize_t
 http_fillbuf(struct httpio *io, size_t len)
 {
 	ssize_t nbytes;
+	char ch;
 
 	if (io->error)
 		return (-1);
@@ -229,7 +230,7 @@ http_fillbuf(struct httpio *io, size_t l
 	if (io->chunksize == 0) {
 		switch (http_new_chunk(io)) {
 		case -1:
-			io->error = 1;
+			io->error = EPROTO;
 			return (-1);
 		case 0:
 			io->eof = 1;
@@ -249,10 +250,8 @@ http_fillbuf(struct httpio *io, size_t l
 	io->chunksize -= io->buflen;
 
 	if (io->chunksize == 0) {
-		char endl[2];
-
-		if (fetch_read(io->conn, endl, 2) != 2 ||
-		    endl[0] != '\r' || endl[1] != '\n')
+		if (fetch_read(io->conn, &ch, 1) != 1 || ch != '\r' ||
+		    fetch_read(io->conn, &ch, 1) != 1 || ch != '\n')
 			return (-1);
 	}
 
@@ -268,31 +267,30 @@ static int
 http_readfn(void *v, char *buf, int len)
 {
 	struct httpio *io = (struct httpio *)v;
-	int l, pos;
+	int rlen;
 
 	if (io->error)
 		return (-1);
 	if (io->eof)
 		return (0);
 
-	for (pos = 0; len > 0; pos += l, len -= l) {
-		/* empty buffer */
-		if (!io->buf || io->bufpos == io->buflen)
-			if (http_fillbuf(io, len) < 1)
-				break;
-		l = io->buflen - io->bufpos;
-		if (len < l)
-			l = len;
-		memcpy(buf + pos, io->buf + io->bufpos, l);
-		io->bufpos += l;
+	/* empty buffer */
+	if (!io->buf || io->bufpos == io->buflen) {
+		if ((rlen = http_fillbuf(io, len)) < 0) {
+			if ((errno = io->error) == EINTR)
+				io->error = 0;
+			return (-1);
+		} else if (rlen == 0) {
+			return (0);
+		}
 	}
 
-	if (!pos && io->error) {
-		if (io->error == EINTR)
-			io->error = 0;
-		return (-1);
-	}
-	return (pos);
+	rlen = io->buflen - io->bufpos;
+	if (len < rlen)
+		rlen = len;
+	memcpy(buf, io->buf + io->bufpos, rlen);
+	io->bufpos += rlen;
+	return (rlen);
 }
 
 /*


More information about the svn-src-stable-10 mailing list