shithub: iso

Download patch

ref: 8fa9d99424da17b8ac3e67fb6d5563bf71f51e56
parent: c7abd2e7be5f3f9aff60f18121d47da13e5b279d
author: moody <moody@remilia>
date: Tue Oct 22 00:38:59 EDT 2024

add torrent seeds and tracker for releases

diff: cannot open b/src/seedbox//null: file does not exist: 'b/src/seedbox//null'
--- /dev/null
+++ b/bin/trackerc
@@ -1,0 +1,116 @@
+#!/bin/rc
+
+# worst bittorrent tacker ever written... in rc.
+dir=/tmp/tracker
+cd $dir || exit 'no tracker directory'
+
+cr='
'
+
+ipv=ip
+ipv6=()
+if(! ~ $#net 1) net=$$#*
+ip=`'!'{cat $net/remote}
+ip=$ip(1)
+~ $#ip 1 || exit 'no remote ip'
+
+if(~ $ip *:*){
+	ipv=ipv6
+	ipv6=$ip
+	ip=()
+}
+
+req=`{read}
+
+q=`'?'{echo -n $req(2)}
+q=`'&'{echo -n $q(2)}
+
+for(i in $q){
+	v=`'='{echo -n $i}
+	k=$v(1)
+	v=$v(2)
+	switch($k){
+	case info_hash peer_id port
+		$k=$v
+	}
+}
+
+# sanity
+~ $#info_hash 1 || exit 'no info hash'
+
+fn hex {
+	xd -x1 | sed 's/^[^ ]+//g;s/[ ]//g;' | sed '{N;s/\n//;}'
+}
+info_hash=`{echo -n $info_hash | urlencode -d | hex}
+
+# sanity
+~ $info_hash ???????????????????????????????????????? || exit 'bad info hash format'
+
+fn respond {
+	echo $ip $req $* >[1=2]
+
+	echo 'HTTP/1.1' $* $cr
+	echo $cr
+}
+
+# is this a scrape?
+if(! ~ $#peer_id 1){
+	if(! test -d $info_hash){
+		respond 404 'Not Found'
+		exit ''
+	}
+}
+
+fn str {
+	n=`{echo -n $1 | wc -c}
+	echo -n $n:$1
+}
+fn int {
+	echo -n i^$1^e
+}
+
+if(~ $#peer_id 1){
+	echo -n $peer_id | urlencode -d > /env/peer_id.bin
+	peer_id=`{hex < /env/peer_id.bin}
+
+	# sanity
+	~ $peer_id ???????????????????????????????????????? || exit 'bad peer id format'
+
+	port=`{echo $port | sed 's/[^0-9]//g'}
+	~ $#port 1 || exit 'no port port'
+	~ $port [0-9]* || exit 'bad port format'
+
+	mkdir -p $info_hash || exit 'mkdir info hash directory'
+
+	# write dict file for classic mode
+	> $info_hash/$peer_id.$ipv.dict {
+		echo -n d
+		str 'peer id'
+		echo -n '20:'
+		cat /env/peer_id.bin
+		str ip
+		str $$ipv
+		str port
+		int $port
+		echo -n e
+	}
+}
+
+cd $info_hash || exit 'cd info hash directory'
+
+# cleanup old files
+for(i in *){
+	test $i -older 5m && rm -f $i
+}
+
+respond 200 OK
+
+echo -n d
+str interval
+int 120
+str peers
+echo -n l
+cat *.dict >[2] /dev/null 
+echo -n e
+echo -n e
+
+exit ''
--- a/cpustart
+++ b/cpustart
@@ -3,4 +3,8 @@
 if(test -r $key){
 	cat $key >/mnt/factotum/ctl
 }
+releases='/usr/build/www/release'
+if(test -d $releases){
+	ip/seedbox $releases
+}
 auth/cron
--- a/mkfile
+++ b/mkfile
@@ -3,6 +3,7 @@
 SRC=\
 	tcp80\
 	execfs\
+	seedbox\
 
 all:V:
 	# nothing
--- /dev/null
+++ b/service/tcp1337
@@ -1,0 +1,3 @@
+#!/bin/rc
+exec alarm 2000 /bin/trackerc $* >>[2]/sys/log/tracker
+
--- /dev/null
+++ b/service/tcp1337.namespace
@@ -1,0 +1,37 @@
+# kernel devices
+bind #c /dev
+bind #d /fd
+bind -c #e /env
+bind #p /proc
+bind -c #s$srvspec /srv
+bind -a #¤ /dev
+bind -qa #¶ /dev
+
+# root
+mount -C /srv/boot /root $rootspec
+bind -a $rootdir /
+
+# mount points
+mount -a /srv/slashn /n
+mount -a /srv/slashmnt /mnt
+mount -a /srv/mntexport /mnt/exportfs
+
+# standard bin
+bind /$cputype/bin /bin
+bind $rootdir/rc /rc
+bind -a /rc/bin /bin
+
+bind -a #l /net
+bind -a #I /net
+bind -a #a /net
+mount -a /srv/cs /net
+mount -a /srv/dns /net
+mount -a /srv/net /net
+
+bind -c /sys/lib/tracker /tmp
+
+. /lib/namespace.local
+. /lib/namespace.$sysname
+. /cfg/$sysname/namespace
+
+chdev Mcde|pslI/
--- /dev/null
+++ b/src/seedbox/mkfile
@@ -1,0 +1,11 @@
+</$objtype/mkfile
+
+TARG=seedbox
+BIN=/$objtype/bin/ip
+CFLAGS=-FTVw
+
+HFILES=
+
+OFILES=seedbox.$O
+
+</sys/src/cmd/mkone
--- /dev/null
+++ b/src/seedbox/seedbox.c
@@ -1,0 +1,167 @@
+#include <u.h>
+#include <libc.h>
+
+typedef struct Seed Seed;
+struct Seed {
+	int pid;
+	char *torrent;
+	int seen;
+};
+static Seed *seeds;
+static int nseeds;
+static char *ddir, *tdir;
+static int tfd;
+
+static void
+spawn(Seed *s, char *t)
+{
+	int p;
+
+	if(t != nil && (s->torrent = strdup(t)) == nil)
+		sysfatal("strdup: %r");
+	switch(p = fork()){
+	case -1:
+		sysfatal("fork: %r");
+	case 0:
+		if(chdir(ddir ? ddir : tdir) < 0)
+			sysfatal("chdir: %r");
+		execl("/bin/ip/torrent", "torrent", "-s", smprint("%s/%s", tdir, s->torrent), nil);
+		sysfatal("exec: %r");
+	default:
+		s->pid = p;
+		return;
+	}
+}
+
+static void
+kill(Seed *s)
+{
+	assert(s->pid != 0);
+	postnote(PNPROC, s->pid, "kill");
+	s->pid = 0;
+	free(s->torrent);
+	s->torrent = nil;
+}
+
+static void
+scandir(void)
+{
+	Dir *d;
+	char **new, *s;
+	int i, j, n, o, p;
+
+	for(j = 0; j < nseeds; j++)
+		seeds[j].seen = 0;
+	if(seek(tfd, 0, 0) != 0)
+		sysfatal("seek: %r");
+	n = dirreadall(tfd, &d);
+	if(n < 0)
+		sysfatal("dirreadall: %r");
+	new = mallocz(sizeof(char*)*n, 1);
+	if(new == nil)
+		sysfatal("malloc: %r");
+	o = 0;
+	for(i = 0; i < n; i++){
+		if((s = strstr(d[i].name, ".torrent")) == nil)
+			continue;
+		if(s[strlen(".torrent")] != '\0')
+			continue;
+		for(j = 0; j < nseeds; j++){
+			if(strcmp(seeds[j].torrent, d[i].name) != 0)
+				continue;
+			if(seeds[j].pid == 0)
+				spawn(seeds+j, nil);
+			seeds[j].seen = 1;
+			break;
+		}
+		if(j == nseeds)
+			new[o++] = d[i].name;
+	}
+	for(j = 0; o > 0 && j < nseeds; j++){
+		if(seeds[j].seen == 1)
+			continue;
+		kill(seeds+j);
+		spawn(seeds+j, new[--o]);
+		seeds[j].seen = 1;
+	}
+	if(o > 0){
+		seeds = realloc(seeds, sizeof(Seed) * (nseeds + o));
+		if(seeds == nil)
+			sysfatal("realloc: %r");
+		for(p = o, j = nseeds; j < nseeds + o; j++){
+			seeds[j].seen = 1;
+			spawn(seeds+j, new[--p]);
+		}
+		nseeds = nseeds + o;
+	}
+	for(j = 0; j < nseeds; j++)
+		if(seeds[j].seen == 0)
+			kill(seeds+j);
+	free(new);
+	free(d);
+}
+
+static int
+catch(void*, char*)
+{
+	int j;
+
+	for(j = 0; j < nseeds; j++)
+		kill(seeds+j);
+	return 0;
+}
+
+_Noreturn void
+usage(void)
+{
+	fprint(2, "%s: tdir <ddir>\n", argv0);
+	exits("usage");
+}
+
+void
+main(int argc, char **argv)
+{
+	int sec;
+	char *n, *r;
+	char buf[128];
+
+	sec = 30;
+	ARGBEGIN{
+	case 'w':
+		n = EARGF(usage());
+		sec = strtol(n, &r, 0);
+		if(n == r)
+			sysfatal("invalid number");
+		break;
+	default:
+		usage();
+	}ARGEND
+
+	switch(argc){
+	default:
+		usage();
+	case 2:
+		ddir = argv[1];
+	case 1:
+		tfd = open(argv[0], OREAD);
+		if(tfd < 0)
+			sysfatal("open: %r");
+		if(fd2path(tfd, buf, sizeof buf) != 0)
+			sysfatal("fd2path: %r");
+		tdir = strdup(buf);
+		if(tdir == nil)
+			sysfatal("tdir: %r");
+	}
+
+	switch(fork()){
+	case -1:
+		sysfatal("fork: %r");
+	case 0:
+		break;
+	default:
+		exits(0);
+	}
+
+	for(atnotify(catch, 1); ; sleep(sec * 1000))
+		scandir();
+}