ref: 2713779ee64250b16314355f76cb90d40b64e4b2
parent: c00c60d327168c25e56077c8310cf2380833e9be
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);
}
}