ip/torrent: udp tracker support
parent
caa6d7701d
commit
d899f9cfc6
|
@ -275,11 +275,29 @@ unpack(uchar *s, int n, char *fmt, ...)
|
|||
if(s+1 > e) goto Err;
|
||||
*va_arg(arg, int*) = *s++;
|
||||
break;
|
||||
case 'w':
|
||||
if(s+2 > e) goto Err;
|
||||
*va_arg(arg, int*) = s[0]<<8 | s[1];
|
||||
s += 2;
|
||||
break;
|
||||
case 'l':
|
||||
if(s+4 > e) goto Err;
|
||||
*va_arg(arg, int*) = s[0]<<24 | s[1]<<16 | s[2]<<8 | s[3];
|
||||
s += 4;
|
||||
break;
|
||||
case 'v':
|
||||
if(s+4 > e) goto Err;
|
||||
*va_arg(arg, vlong*) =
|
||||
(vlong)s[0]<<56 |
|
||||
(vlong)s[1]<<48 |
|
||||
(vlong)s[2]<<40 |
|
||||
(vlong)s[3]<<32 |
|
||||
(vlong)s[4]<<24 |
|
||||
(vlong)s[5]<<16 |
|
||||
(vlong)s[6]<<8 |
|
||||
(vlong)s[7];
|
||||
s += 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
va_end(arg);
|
||||
|
@ -294,6 +312,7 @@ pack(uchar *s, int n, char *fmt, ...)
|
|||
{
|
||||
va_list arg;
|
||||
uchar *b, *e;
|
||||
vlong v;
|
||||
int i;
|
||||
|
||||
b = s;
|
||||
|
@ -310,6 +329,12 @@ pack(uchar *s, int n, char *fmt, ...)
|
|||
if(s+1 > e) goto Err;
|
||||
*s++ = i & 0xFF;
|
||||
break;
|
||||
case 'w':
|
||||
i = va_arg(arg, int);
|
||||
if(s+2 > e) goto Err;
|
||||
*s++ = (i>>8) & 0xFF;
|
||||
*s++ = i & 0xFF;
|
||||
break;
|
||||
case 'l':
|
||||
i = va_arg(arg, int);
|
||||
if(s+4 > e) goto Err;
|
||||
|
@ -318,10 +343,22 @@ pack(uchar *s, int n, char *fmt, ...)
|
|||
*s++ = (i>>8) & 0xFF;
|
||||
*s++ = i & 0xFF;
|
||||
break;
|
||||
case 'v':
|
||||
v = va_arg(arg, vlong);
|
||||
if(s+8 > e) goto Err;
|
||||
*s++ = (v>>56) & 0xFF;
|
||||
*s++ = (v>>48) & 0xFF;
|
||||
*s++ = (v>>40) & 0xFF;
|
||||
*s++ = (v>>32) & 0xFF;
|
||||
*s++ = (v>>24) & 0xFF;
|
||||
*s++ = (v>>16) & 0xFF;
|
||||
*s++ = (v>>8) & 0xFF;
|
||||
*s++ = v & 0xFF;
|
||||
break;
|
||||
case '*':
|
||||
i = va_arg(arg, int);
|
||||
if(s+i > e) goto Err;
|
||||
memmove(s, va_arg(arg, uchar*), i);
|
||||
memmove(s, va_arg(arg, void*), i);
|
||||
s += i;
|
||||
break;
|
||||
}
|
||||
|
@ -727,38 +764,15 @@ Error:
|
|||
}
|
||||
|
||||
void
|
||||
tracker(char *url)
|
||||
webtracker(char *url)
|
||||
{
|
||||
static Dict *trackers;
|
||||
static QLock trackerslk;
|
||||
|
||||
char *event, *p;
|
||||
Dict *d, *l;
|
||||
int n, fd;
|
||||
|
||||
if(url == nil)
|
||||
return;
|
||||
|
||||
qlock(&trackerslk);
|
||||
if(dlook(trackers, url)){
|
||||
qunlock(&trackerslk);
|
||||
return;
|
||||
}
|
||||
n = strlen(url);
|
||||
d = mallocz(sizeof(*d) + n+1, 1);
|
||||
strcpy(d->str, url);
|
||||
d->len = n;
|
||||
d->typ = 'd';
|
||||
d->val = d;
|
||||
d->next = trackers;
|
||||
trackers = d;
|
||||
url = d->str;
|
||||
qunlock(&trackerslk);
|
||||
|
||||
if(debug) fprint(2, "tracker %s\n", url);
|
||||
|
||||
if(rfork(RFPROC|RFMEM))
|
||||
return;
|
||||
if(debug) fprint(2, "webtracker %s\n", url);
|
||||
|
||||
event = "&event=started";
|
||||
for(;;){
|
||||
|
@ -807,6 +821,143 @@ tracker(char *url)
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
udpaddr(char addr[64], int naddr, char *url)
|
||||
{
|
||||
int port;
|
||||
char *x;
|
||||
|
||||
if((url = strchr(url, ':')) == nil)
|
||||
return -1;
|
||||
url++;
|
||||
while(*url == '/')
|
||||
url++;
|
||||
if(x = strchr(url, ':')){
|
||||
port = atoi(x+1);
|
||||
} else {
|
||||
port = 80;
|
||||
if((x = strchr(url, '/')) == nil)
|
||||
x = strchr(url, 0);
|
||||
}
|
||||
snprint(addr, naddr, "udp!%.*s!%d", (int)(x-url), url, port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
udptracker(char *url)
|
||||
{
|
||||
uchar buf[MAXIO], *p, *e;
|
||||
int fd, event, n, a, i;
|
||||
int transid, interval;
|
||||
vlong connid;
|
||||
char addr[64];
|
||||
|
||||
if(udpaddr(addr, sizeof(addr), url) < 0)
|
||||
return;
|
||||
if(rfork(RFPROC|RFMEM))
|
||||
return;
|
||||
if(debug) fprint(2, "udptracker %s\n", addr);
|
||||
|
||||
event = 1;
|
||||
for(;;){
|
||||
alarm(30000);
|
||||
if((fd = dial(addr, 0, 0, 0)) < 0)
|
||||
goto Sleep;
|
||||
|
||||
/* connect */
|
||||
transid = rand();
|
||||
n = pack(buf, sizeof(buf), "vll", 0x41727101980LL, 0, transid);
|
||||
if(write(fd, buf, n) != n)
|
||||
goto Sleep;
|
||||
for(;;){
|
||||
if((n = read(fd, buf, sizeof(buf))) <= 0)
|
||||
goto Sleep;
|
||||
if(unpack(buf, n, "llv", &a, &i, &connid) < 0)
|
||||
continue;
|
||||
if(a == 0 && i == transid)
|
||||
break;
|
||||
}
|
||||
alarm(0);
|
||||
|
||||
/* announce */
|
||||
transid = rand();
|
||||
lock(&stats);
|
||||
n = pack(buf, sizeof(buf), "vll**vvvl____llw",
|
||||
connid, 1, transid,
|
||||
sizeof(infohash), infohash,
|
||||
sizeof(peerid), peerid,
|
||||
stats.down,
|
||||
stats.left,
|
||||
stats.up,
|
||||
event,
|
||||
0, -1,
|
||||
port);
|
||||
unlock(&stats);
|
||||
|
||||
interval = 0;
|
||||
alarm(30000);
|
||||
if(write(fd, buf, n) != n)
|
||||
goto Sleep;
|
||||
for(;;){
|
||||
if((n = read(fd, buf, sizeof(buf))) <= 0)
|
||||
goto Sleep;
|
||||
e = buf+n;
|
||||
if((n = unpack(buf, n, "lll________", &a, &i, &interval)) < 0)
|
||||
continue;
|
||||
if(a == 1 && i == transid){
|
||||
for(p = buf+n; p+6 <= e; p += 6){
|
||||
char ip[16], port[6];
|
||||
|
||||
snprint(ip, sizeof(ip), "%d.%d.%d.%d",
|
||||
p[0], p[1], p[2], p[3]);
|
||||
snprint(port, sizeof(port), "%d", p[4]<<8 | p[5]);
|
||||
client(ip, port);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
event = 0;
|
||||
Sleep:
|
||||
alarm(0);
|
||||
if(fd >= 0)
|
||||
close(fd);
|
||||
if(interval < 10 | interval > 60*60)
|
||||
interval = 2*60;
|
||||
sleep(interval * 1000 + nrand(5000));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tracker(char *url)
|
||||
{
|
||||
static Dict *trackers;
|
||||
static QLock trackerslk;
|
||||
Dict *d;
|
||||
int n;
|
||||
|
||||
if(url == nil)
|
||||
return;
|
||||
qlock(&trackerslk);
|
||||
if(dlook(trackers, url)){
|
||||
qunlock(&trackerslk);
|
||||
return;
|
||||
}
|
||||
n = strlen(url);
|
||||
d = mallocz(sizeof(*d) + n+1, 1);
|
||||
strcpy(d->str, url);
|
||||
d->len = n;
|
||||
d->typ = 'd';
|
||||
d->val = d;
|
||||
d->next = trackers;
|
||||
trackers = d;
|
||||
url = d->str;
|
||||
qunlock(&trackerslk);
|
||||
if(!cistrncmp(url, "udp:", 4))
|
||||
udptracker(url);
|
||||
else
|
||||
webtracker(url);
|
||||
}
|
||||
|
||||
int
|
||||
Hfmt(Fmt *f)
|
||||
{
|
||||
|
@ -946,8 +1097,10 @@ fixnamedup(char *s)
|
|||
}
|
||||
|
||||
int
|
||||
killnote(void *, char *)
|
||||
catch(void *, char *msg)
|
||||
{
|
||||
if(strstr(msg, "alarm"))
|
||||
return 1;
|
||||
postnote(PNGROUP, killgroup, "kill");
|
||||
return 0;
|
||||
}
|
||||
|
@ -1125,7 +1278,7 @@ main(int argc, char *argv[])
|
|||
havepiece(i);
|
||||
|
||||
srand(time(0));
|
||||
atnotify(killnote, 1);
|
||||
atnotify(catch, 1);
|
||||
switch(i = rfork(RFPROC|RFMEM|RFNOTEG)){
|
||||
case -1:
|
||||
sysfatal("fork: %r");
|
||||
|
|
Loading…
Reference in New Issue