summaryrefslogblamecommitdiffstats
path: root/src/main.c
blob: bcf7f9814469349691ed440f86d51df9a0664768 (plain) (tree)
1
2
3
4
5
6
7
8
9
10


                   




                     

                     
                          
                            

                                                                                    
                
                                                                                           
                

                    
                








                                      


                                  

         
                      

                                                                                                          

                            






                                                         
                
                             
                                                                          

                                        
                                                                                 
                                                                      
                               




                                        
                                                                  
                                  
         
 
                                   


                                       
                  
                                

                                         









                                                                                  

                                                                                  

                                       
                                                                           
                                              
                                                                                  
                                              
                                                                                  

                                                                                  
                                                          
                                                                           
                                      
                                



                                          


                                                           
                                                                         
                        
                                                                                           

                                                                    
                                                                                  


                                                                                   
                       

                       

                                                                                                                              
                       

                       
                                                        
                               
                               
                      













                                                                                                                                                                                                                      







                                              
                                                                                                                                                                                                                           

                                       
                                                  
                                                                                                                      
                                                                                                       
                                                                              
                                  
                      
                           
  



                                                                
                                       









                                           
                          
         




                                                       
                                               



                                                
                                                   









                                                                                    

                                
         
          

                                 
                   

                                                                                                
                        




                                                                                                   
                        



                                                                                                                              
                        


                             
          



                              



                                       



                                                                                                

                              
                                                                                                                                       
                 
 
#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 : "")
#define So(x, o) (x ? x : o)
#define TORRENT_USERDATA struct dht * dht;
#define DHT_USERDATA struct pollfd ** pollfds; size_t * pollfds_size; nfds_t * nfds;
#include <dht.c>
#define DISCONNECTION_MIXIN_BOTTOM if (t->dl->flags & goodmeta) t->type &= ~(info | peers);
#include <tcp.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;
	}
}
time_t last_added = 0;
void found_torrent (struct dht * d __attribute__((unused)), const unsigned char * h, struct torrent * t) {
	char buf[128];
	bin2hex(buf, h, 20);
	buf[40] = '\0';
	struct stat statbuf;
	strcat(buf, ".torrent");
	if (!stat(buf, &statbuf)) {
		L(expected, d, "%s already exists", buf);
		return;
	}
	L(debug, d, "%s%s", buf, t ? " stored" : " new");
	if (t) {
		if (!t->type)
			t->ttl = seconds()+atoi(So(getenv("TTL"), "256"));
		t->type |= info | peers;
	} else {
		if (last_added + atoi(So(getenv("COOLDOWN"), "2")) > seconds()) {
			L(debug, d, "not adding a torrent this fast");
			return;
		}
		last_added = seconds();
		t = torrent_init();
		memcpy(t->hash, h, 20);
		t->type |= info | peers;
		t->ttl = seconds()+atoi(So(getenv("TTL"), "256"));
		add_torrent(d, t);
	}
}
int main (int argc, char ** argv) {
	size_t pollfds_size = 1;
	nfds_t nfds = 1;
	struct pollfd * pollfds = NULL;
	int r = 0;
	struct dht * dht = NULL;
	char * cfr = NULL;
	struct bencoding * config = 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 (sigaddset(&sigset, SIGTERM) == -1)
		error_at_line(8, errno, __FILE__, __LINE__, "sigaddset(SIGTERM)");
	if (sigprocmask(SIG_UNBLOCK, &sigset, NULL) == -1)
		error_at_line(9, errno, __FILE__, __LINE__, "sigprocmask");
	struct itimerval itimerval = {
		.it_interval = {
			.tv_sec = PERIODIC
		},
		.it_value = {
			.tv_sec = PERIODIC
		}
	};
	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", 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;
	}
	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;
	}
	config = bdecode(cfr, statbuf.st_size, replace);
	dht = dht_init(config);
	free_bencoding(config);
	config = NULL;
	if (getenv("INSERT_PEER")) {
		dht->insert_peer.sin6_family = AF_INET6;
		dht->insert_peer.sin6_port = htons(atoi(So(getenv("INSERT_PEER_PORT"), "1337")));
		if (inet_pton(AF_INET6, getenv("INSERT_PEER"), dht->insert_peer.sin6_addr.s6_addr) != 1) {
			error_at_line(0, 0, __FILE__, __LINE__, "inet_pton(AF_INET6, getenv(INSERT_PEER)) != 1");
			r = 14;
			goto r;
		}
		error_at_line(0, 0, __FILE__, __LINE__, "feature INSERT_PEER not implemented completely -- bugs: travnik somehow starts sending packets to inserted peer ... perhaps he sends get_peers to himself?");
		r = 15;
		goto r;
	}
	if (getenv("TOOMUCH"))
		dht->toomuch = atoi(getenv("TOOMUCH"));
	dht->possible_torrent = found_torrent;
	dht->connection = connection;
	pollfds = malloc(sizeof *pollfds);
	pollfds[0].fd = dht->socket;
	pollfds[0].events = POLLIN;
	dht->pollfds = &pollfds;
	dht->pollfds_size = &pollfds_size;
	dht->nfds = &nfds;
	dht->verbosity |= (getenv("TRAVNIK_INCOMING_DHT") ? incoming_dht : 0) | (getenv("TRAVNIK_OUTGOING_DHT") ? outgoing_dht : 0) | (getenv("TRAVNIK_DEBUG") ? debug : 0) | (getenv("TRAVNIK_EXŠECTED") ? expected : 0);
	dht->torrents_max = K;
	dht->peers_per_torrent_max = K;
	struct torrent * torrent = torrent_init();
	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 = /* (useless, since we have no listening system yet) announce | */ peers | info;
	torrent->ttl = seconds()+128; /**< idk, enough to bootstrap i guess */
	add_torrent(dht, torrent);
	periodic(dht);
	// alarm(PERIODIC);
w:
	while (poll(pollfds, nfds, -1) != -1) { // can't timeout
		if (sigusr1) {
			sigusr1 = 0;
			dht_print(stdout, dht);
			fflush(stdout);
			goto w;
		}
		if (periodično) {
			periodično = 0;
			// alarm(PERIODIC);
			periodic(dht);
			goto w;
		}
		if (samomor)
			goto s;
		work(dht);
	}
	switch (errno) {
		case EINTR:
			if (sigusr1) {
				sigusr1 = 0;
				dht_print(stdout, dht);
				fflush(stdout);
				goto w;
			}
			if (periodično) {
				periodično = 0;
				// alarm(PERIODIC);
				periodic(dht);
				goto w;
			}
			if (!samomor) {
				error_at_line(0, errno, __FILE__, __LINE__, "poll");
				r = 114;
			}
			break;
		default:
			error_at_line(0, errno, __FILE__,  __LINE__, "poll");
			r = 115;
			goto r;
	}
	s:
	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);
	r:
	if (dht) {
		dht_free(dht);
		dht = NULL;
	}
	if (config) {
		free_bencoding(config);
		config = 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)");
	if (pollfds)
		free(pollfds);
	fprintf(stderr, "exiting cleanly with status %d node_init_count=%u node_free_count=%u\n", r, node_init_count, node_free_count);
	return r;
}