#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <error.h>
#include <fcntl.h>
#include <signal.h>
#include <poll.h>
#include <sys/time.h>
#define S0(x) (x ? x : "")
#include <dht.c>
int samomor = 0;
int periodično = 0;
int sigusr1 = 0;
void handler (int s) {
switch (s) {
case SIGINT:
case SIGTERM:
samomor++;
break;
case SIGALRM:
periodično++;
break;
case SIGUSR1:
sigusr1++;
break;
}
}
void found_torrent (struct dht * d __attribute__((unused)), const unsigned char * h) {
char buf[41];
bin2hex(buf, h, 20);
buf[40] = '\0';
L(stdout, "magnet:?xt=urn:btih:%s", buf);
}
int main (int argc, char ** argv) {
int r = 0;
struct dht * dht = NULL;
struct sigaction sigact = {
.sa_handler = handler,
.sa_flags = SA_RESTART
};
if (sigaction(SIGALRM, &sigact, NULL) == -1)
error_at_line(1, errno, __FILE__, __LINE__, "sigaction(SIGALRM)");
if (sigaction(SIGINT, &sigact, NULL) == -1)
error_at_line(2, errno, __FILE__, __LINE__, "sigaction(SIGINT)");
if (sigaction(SIGTERM, &sigact, NULL) == -1)
error_at_line(3, errno, __FILE__, __LINE__, "sigaction(SIGTERM)");
if (sigaction(SIGUSR1, &sigact, NULL) == -1)
error_at_line(4, errno, __FILE__, __LINE__, "sigaction(SIGUSR1)");
sigset_t sigset;
if (sigemptyset(&sigset) == -1)
error_at_line(5, errno, __FILE__, __LINE__, "sigemptyset");
if (sigaddset(&sigset, SIGUSR1) == -1)
error_at_line(6, errno, __FILE__, __LINE__, "sigaddset(SIGUSR1)");
if (sigaddset(&sigset, SIGALRM) == -1)
error_at_line(7, errno, __FILE__, __LINE__, "sigaddset(SIGALRM)");
if (sigprocmask(SIG_UNBLOCK, &sigset, NULL) == -1)
error_at_line(8, errno, __FILE__, __LINE__, "sigprocmask");
/* struct itimerval itimerval = {
.it_interval = {
.tv_sec = 60
}
};
if (setitimer(ITIMER_REAL, &itimerval, NULL) == -1)
error_at_line(9, errno, __FILE__, __LINE__, "setitimer"); */
if (argc != 1+1)
error_at_line(10, 0, __FILE__, __LINE__, "%s configfile.ben >> possible_torrents.L", S0(argv[0]));
int cf = open(argv[1], O_RDWR | O_CLOEXEC | O_CREAT, 00664);
if (cf == -1)
error_at_line(11, errno, __FILE__, __LINE__, "open(%s)", argv[1]);
struct stat statbuf;
if (fstat(cf, &statbuf) == -1) {
error_at_line(0, errno, __FILE__, __LINE__, "fstat(cf, &statbuf)");
r = 12;
goto r;
}
char * cfr = NULL;
if (statbuf.st_size && !(cfr = mmap(NULL, statbuf.st_size, PROT_READ, MAP_SHARED, cf, 0))) {
error_at_line(0, errno, __FILE__, __LINE__, "mmap(NULL, %ld, PROT_READ, MAP_SHARED, cf, 0)", statbuf.st_size);
r = 13;
goto r;
}
struct bencoding * config = bdecode(cfr, statbuf.st_size, replace);
dht = dht_init(config);
dht->possible_torrent = found_torrent;
free_bencoding(config);
struct torrent * torrent = calloc(1, sizeof *torrent);
memcpy(torrent->hash, "\xdd\x82\x55\xec\xdc\x7c\xa5\x5f\xb0\xbb\xf8\x13\x23\xd8\x70\x62\xdb\x1f\x6d\x1c", 20);
torrent->type = announce | peers;
add_torrent(dht, torrent);
struct pollfd pollfd = {
.fd = dht->socket,
.events = POLLIN
};
w:
alarm(13*60);
while (poll(&pollfd, 1, -1) == 1)
work(dht);
if (errno == EINTR) {
if (sigusr1) {
sigusr1 = 0;
dht_print(stdout, dht);
goto w;
}
if (periodično) {
periodično = 0;
work(dht);
goto w;
}
if (!samomor) {
error_at_line(0, errno, __FILE__, __LINE__, "poll");
r = 114;
}
} else {
error_at_line(0, errno, __FILE__, __LINE__, "poll");
r = 115;
goto r;
}
config = persistent(dht);
dht_free(dht);
dht = NULL;
if (cfr && munmap(cfr, statbuf.st_size) == -1) {
error_at_line(0, errno, __FILE__, __LINE__, "munmap(cf, %ld)", statbuf.st_size);
r = 116;
goto r;
}
cfr = NULL;
if (ftruncate(cf, (statbuf.st_size = bencode_length(config))) == -1) {
error_at_line(0, errno, __FILE__, __LINE__, "ftruncate(cf, %ld)", statbuf.st_size);
r = 117;
goto r;
}
if (!(cfr = mmap(NULL, statbuf.st_size, PROT_WRITE, MAP_SHARED, cf, 0))) {
error_at_line(0, errno, __FILE__, __LINE__, "mmap(NULL, %ld, PROT_READ, MAP_SHARED, cf, 0)", statbuf.st_size);
r = 118;
goto r;
}
bencode(cfr, config);
free_bencoding(config);
config = NULL;
r:
if (dht) {
dht_free(dht);
dht = NULL;
}
if (cfr && munmap(cfr, statbuf.st_size) == -1)
error_at_line(0, errno, __FILE__, __LINE__, "munmap(cf, %ld)", statbuf.st_size);
if (close(cf) == -1)
error_at_line(0, errno, __FILE__, __LINE__, "close(cf)");
L(stderr, "exiting cleanly with status %d\n", r);
return r;
}