git: 9front

Download patch

ref: 250d86f997647a16b1e9b2639d25d705f1f69f52
parent: 4fa6ca6696185364c89c772a927e6204cb916e3b
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Wed Jul 22 23:24:39 EDT 2015

ip/httpfile: fix flushes, fix concurrent reads, set error string

Tflush handling was wrong, we cannot respond to the old
request if we have not actually removed the req from the
in progress block queue.

when reads are issued concurrently, we have to set b->len
before the block is inserted into the inprogress list.
otherwise findblock() is unable to find it and no requests
can be queued on the block. this caused the same offset
to be downloaded multiple times.

set the errstr in getrange() so in case of an error, we dont
get some random previous error string.

--- a/sys/src/cmd/ip/httpfile.c
+++ b/sys/src/cmd/ip/httpfile.c
@@ -100,6 +100,8 @@
 			*l = r->aux;
 			if(*l == nil)
 				b->erq = l;
+			r->aux = nil;
+			respond(r, "interrupted");
 			return;
 		}
 	}
@@ -205,10 +207,6 @@
 	int fd, cfd;
 	uchar *data;
 
-	b->len = Blocksize;
-	if(b->off + b->len > size)
-		b->len = size - b->off;
-
 	if(debug)
 		print("getrange: %lld %lld\n", b->off, b->len);
 
@@ -230,6 +228,8 @@
 		close(fd);
 		return nil;
 	}
+
+	werrstr("bad contentrange header");
 	if(readstring(cfd, buf, sizeof(buf)) <= 0){
 Badrange:
 		close(cfd);
@@ -244,6 +244,7 @@
 
 	/* read body data */
 	data = emalloc9p(b->len);
+	werrstr("body data truncated");
 	if(readfile(fd, (char*)data, b->len) != b->len){
 		close(fd);
 		free(data);
@@ -410,6 +411,9 @@
 	if((b = findblock(&inprogress, r->ifcall.offset)) == nil){
 		b = emalloc9p(sizeof(Block));
 		b->off = r->ifcall.offset - (r->ifcall.offset % Blocksize);
+		b->len = Blocksize;
+		if(b->off + b->len > size)
+			b->len = size - b->off;
 		addblock(&inprogress, b);
 		if(inprogress.first == b)
 			sendp(httpchan, b);
@@ -467,10 +471,11 @@
 		switch(r->ifcall.type){
 		case Tflush:
 			o = r->oldreq;
-			b = findblock(&inprogress, o->ifcall.offset);
-			if(b != nil)
-				delreq(b, o);
-			respond(o, "interrupted");
+			if(o->ifcall.type == Tread){
+				b = findblock(&inprogress, o->ifcall.offset);
+				if(b != nil)
+					delreq(b, o);
+			}
 			respond(r, nil);
 			break;
 		case Tread:
--