git: 9front

Download patch

ref: ba241f26db60d4cd0dd6a3ad20efc02b328f1e13
parent: 6eaa107b7584ca3175571adbadff2f99dfbc723f
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Apr 30 20:01:14 EDT 2017

ip/torrent: avoid requesting same chunks

instead of always just requesting the missing range
of the current piece, remember the workpiece offset
and request sequential chunks from the workpiece.

this avoids double requests of the same ranges when
the peer does not respond with the data immidiately.

--- a/sys/src/cmd/ip/torrent.c
+++ b/sys/src/cmd/ip/torrent.c
@@ -55,7 +55,7 @@
 char *deftrack = "http://exodus.desync.com/announce";
 char *mntweb = "/mnt/web";
 char *useragent = "torrent";
-uchar infohash[20];
+uchar infohash[SHA1dlen];
 uchar peerid[20];
 int blocksize;
 
@@ -212,9 +212,9 @@
 }
 
 int
-havepiece(int x)
+havepiece(int x, char *from)
 {
-	uchar *p, m, hash[20];
+	uchar *p, m, hash[SHA1dlen];
 	int n;
 
 	m = 0x80>>(x&7);
@@ -228,8 +228,11 @@
 	}
 	sha1(p, n, hash, nil);
 	free(p);
-	if(memcmp(hash, pieces[x].hash, 20))
+	if(memcmp(hash, pieces[x].hash, sizeof(hash))){
+		if(debug && from != nil)
+			fprint(2, "peer %s: damaged piece %d\n", from, x);
 		return 0;
+	}
 	lock(&stats);
 	if((havemap[x>>3] & m) == 0){
 		havemap[x>>3] |= m;
@@ -237,6 +240,8 @@
 		stats.left -= pieces[x].len;
 	}
 	unlock(&stats);
+	if(debug && from != nil)
+		fprint(2, "peer %s: completed piece %d\n", from, x);
 	return 1;
 }
 
@@ -382,7 +387,7 @@
 	uchar buf[64+MAXIO], *map, *told, *p, m;
 	int mechoking, hechoking;
 	int mewant, hewant;
-	int workpiece;
+	int workpiece, workoffset;
 	int i, o, l, x, n;
 
 	if(debug) fprint(2, "peer %s: %s connected\n", addr, incoming ? "incoming" : "outgoing");
@@ -419,6 +424,8 @@
 	mewant = 0;
 	hewant = 0;
 	workpiece = -1;
+	workoffset = 0;
+
 	map = mallocz(nhavemap, 1);
 	told = malloc(nhavemap);
 
@@ -451,18 +458,15 @@
 		}
 		if(!hechoking && mewant){
 			x = workpiece;
-			if(x < 0 || (havemap[x>>3]&(0x80>>(x&7))) != 0)
+			if(x < 0 || (havemap[x>>3]&(0x80>>(x&7))) != 0 || workoffset >= pieces[x].len)
 				x = pickpiece(map);
 			if(x >= 0){
-				workpiece = x;
-				o = pieces[x].brk;
-				if(o < 0 || o >= pieces[x].len){
-					pieces[x].brk = 0;
-					o = 0;
-				}
+				o = workpiece != x ? pieces[x].brk : workoffset;
 				l = pieces[x].len - o;
 				if(l > MAXIO)
 					l = MAXIO;
+				workpiece = x;
+				workoffset = o + l; 
 				if(debug) fprint(2, "peer %s: -> request %d %d %d\n", addr, x, o, l);
 				n = pack(buf, sizeof(buf), "lblll", 1+4+4+4, 0x06, x, o, l);
 				if(write(fd, buf, n) != n)
@@ -566,7 +570,8 @@
 			if(n <= 0)
 				continue;
 			pieces[x].brk = o+n;
-			if(o+n >= pieces[x].len && !havepiece(x)){
+			if(o+n >= pieces[x].len && !havepiece(x, addr)){
+				pieces[x].brk = 0;
 				/* backoff from this piece for a while */
 				if(x == workpiece)
 					workpiece = -1;
@@ -797,7 +802,7 @@
 			o += m;
 			n -= m;
 			p = 0;
-			if(havepiece(x++))
+			if(havepiece(x++, w->str))
 				continue;
 			if(++err > 10){
 				close(fd);
@@ -806,8 +811,8 @@
 			}
 		}
 	}
-	havepiece(off / blocksize);
-	havepiece(f->off / blocksize);
+	havepiece(off / blocksize, w->str);
+	havepiece(f->off / blocksize, w->str);
 	close(fd);
 	exits(0);
 }
@@ -1033,7 +1038,7 @@
 int
 mktorrent(int fd, Dict *alist, Dict *wlist)
 {
-	uchar *b, h[20];
+	uchar *b, h[SHA1dlen];
 	Dir *d;
 	int n;
 
@@ -1321,14 +1326,14 @@
 	if((blocksize = atoi(s)) <= 0)
 		sysfatal("bogus piece length in meta info");
 	d = dlook(info, "pieces");
-	if(d == nil || d->typ != 's' || d->len <= 0 || d->len % 20)
+	if(d == nil || d->typ != 's' || d->len <= 0 || d->len % SHA1dlen)
 		sysfatal("bad or no pices in meta info");
-	npieces = d->len / 20;
+	npieces = d->len / SHA1dlen;
 	pieces = mallocz(sizeof(Piece) * npieces, 1);
 	nhavemap = (npieces+7) / 8;
 	havemap = mallocz(nhavemap, 1);
 	for(i = 0; i<npieces; i++){
-		pieces[i].hash = (uchar*)d->str + i*20;
+		pieces[i].hash = (uchar*)d->str + i*SHA1dlen;
 		if(len < blocksize)
 			pieces[i].len = len;
 		else
@@ -1345,7 +1350,7 @@
 			sysfatal("fork: %r");
 		case 0:
 			for(; i<npieces; i+=nproc)
-				havepiece(i);
+				havepiece(i, nil);
 			exits(0);
 		}
 	}
--