#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;
void handler (int s) {
switch (s) {
case SIGINT:
case SIGTERM:
samomor++;
break;
case SIGALRM:
periodično++;
break;
}
}
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 (argc != 1+1)
error_at_line(4, 0, __FILE__, __LINE__, "%s configfile.ben", S0(argv[0]));
int cf = open(argv[1], O_RDWR | O_CLOEXEC | O_CREAT, 00664);
if (cf == -1)
error_at_line(5, 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 = 6;
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 = 7;
goto r;
}
struct bencoding * config = bdecode(cfr, statbuf.st_size, replace);
dht = dht_init(config);
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);
work(dht);
struct pollfd pollfd = {
.fd = dht->socket,
.events = POLLIN
};
struct itimerval itimerval = {
.it_interval = {
.tv_sec = 13*60
}
};
setitimer(ITIMER_REAL, &itimerval, NULL);
w:
while (poll(&pollfd, 1, -1) == 1) {
work(dht);
}
if (errno == EINTR) {
if (periodično) {
periodično = 0;
work(dht);
goto w;
}
if (!samomor) {
error_at_line(0, errno, __FILE__, __LINE__, "poll");
r = 108;
}
} else {
error_at_line(0, errno, __FILE__, __LINE__, "poll");
r = 109;
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 = 110;
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 = 111;
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 = 112;
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)");
return r;
}