summaryrefslogtreecommitdiffstats
path: root/lib/libfetch/http.c
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>2014-01-28 12:48:17 +0000
committerdes <des@FreeBSD.org>2014-01-28 12:48:17 +0000
commit2010baa9c1222ce144a45f1d7485b958e9be88fd (patch)
treea563a19143ca0971436134fef3e8f7eea5e74bd2 /lib/libfetch/http.c
parent86c4a7f196f3692d803d8c2b0595762ce2a9b608 (diff)
downloadFreeBSD-src-2010baa9c1222ce144a45f1d7485b958e9be88fd.zip
FreeBSD-src-2010baa9c1222ce144a45f1d7485b958e9be88fd.tar.gz
Solve http buffering issues and hangs once and for all (hopefully!) by
simply not trying to return exactly what the caller asked for - just return whatever we got and let the caller be the judge of whether it was enough. If an error occurs or the connection times out after we already received some data, return a short read, under the assumption that the next call will fail or time out before we read anything. As it turns out, none of the code that calls fetch_read() assumes an all-or-nothing result anyway, except for a couple of lines where we read the CR LF at the end of a hunk in HTTP hunked encoding, so the changes outside of fetch_read() and http_readfn() are minimal. While there, replace select(2) with poll(2). MFC after: 3 days
Diffstat (limited to 'lib/libfetch/http.c')
-rw-r--r--lib/libfetch/http.c38
1 files changed, 17 insertions, 21 deletions
diff --git a/lib/libfetch/http.c b/lib/libfetch/http.c
index 87535f0..fc43a97 100644
--- a/lib/libfetch/http.c
+++ b/lib/libfetch/http.c
@@ -208,6 +208,7 @@ static int
http_fillbuf(struct httpio *io, size_t len)
{
ssize_t nbytes;
+ char ch;
if (io->error)
return (-1);
@@ -249,10 +250,8 @@ http_fillbuf(struct httpio *io, size_t len)
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,28 @@ 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 (http_fillbuf(io, len) < 1) {
+ if (io->error == EINTR)
+ io->error = 0;
+ return (-1);
+ }
}
- 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);
}
/*
OpenPOWER on IntegriCloud