running. * Added --downloaders and --max-peers options and hopefully usefull defaults. Because curl uses fd_sets it's important to keep the numbers of fds used below FD_SETSIZE. I will probably move the curl stuff to it's own process to get rid of that limitation. * Added to the help text.master
@@ -1,7 +1,7 @@ | |||||
bin_PROGRAMS=btpd | bin_PROGRAMS=btpd | ||||
btpd_SOURCES=\ | btpd_SOURCES=\ | ||||
btpd.c btpd.h\ | btpd.c btpd.h\ | ||||
content.c content.h\ | cli_if.c content.c content.h\ | ||||
download.c download_subr.c download.h\ | download.c download_subr.c download.h\ | ||||
http.c http.h\ | http.c http.h\ | ||||
main.c\ | main.c\ | ||||
@@ -216,7 +216,7 @@ btpd_init(void) | |||||
td_init(); | td_init(); | ||||
http_init(); | http_init(); | ||||
net_init(); | net_init(); | ||||
//ipc_init(); | ipc_init(); | ||||
ul_init(); | ul_init(); | ||||
cm_init(); | cm_init(); | ||||
@@ -36,20 +36,27 @@ cmd_stat(int argc, const char *args, FILE *fp) | |||||
errdie(buf_print(&iob, "9:ntorrentsi%ue", btpd_get_ntorrents())); | errdie(buf_print(&iob, "9:ntorrentsi%ue", btpd_get_ntorrents())); | ||||
errdie(buf_swrite(&iob, "8:torrentsl")); | errdie(buf_swrite(&iob, "8:torrentsl")); | ||||
BTPDQ_FOREACH(tp, btpd_get_torrents(), entry) { | BTPDQ_FOREACH(tp, btpd_get_torrents(), entry) { | ||||
if (tp->state != T_ACTIVE) | |||||
continue; | |||||
uint32_t seen_npieces = 0; | uint32_t seen_npieces = 0; | ||||
for (uint32_t i = 0; i < tp->meta.npieces; i++) | for (uint32_t i = 0; i < tp->meta.npieces; i++) | ||||
if (tp->piece_count[i] > 0) | if (tp->net->piece_count[i] > 0) | ||||
seen_npieces++; | seen_npieces++; | ||||
errdie(buf_print(&iob, "d4:downi%jue", (intmax_t)tp->downloaded)); | errdie(buf_print(&iob, "d4:downi%jue", (intmax_t)tp->net->downloaded)); | ||||
errdie(buf_swrite(&iob, "4:hash20:")); | errdie(buf_swrite(&iob, "4:hash20:")); | ||||
errdie(buf_write(&iob, tp->meta.info_hash, 20)); | errdie(buf_write(&iob, tp->meta.info_hash, 20)); | ||||
errdie(buf_print(&iob, "12:have npiecesi%ue", tp->have_npieces)); | errdie(buf_print(&iob, "4:havei%jde", (intmax_t)cm_get_size(tp))); | ||||
errdie(buf_print(&iob, "6:npeersi%ue", tp->npeers)); | errdie(buf_print(&iob, "6:npeersi%ue", tp->net->npeers)); | ||||
errdie(buf_print(&iob, "7:npiecesi%ue", tp->meta.npieces)); | errdie(buf_print(&iob, "7:npiecesi%ue", tp->meta.npieces)); | ||||
errdie(buf_print(&iob, "4:path%d:%s", | errdie(buf_print(&iob, "4:path%d:%s", | ||||
(int)strlen(tp->relpath), tp->relpath)); | (int)strlen(tp->relpath), tp->relpath)); | ||||
errdie(buf_print(&iob, "2:rdi%lue", tp->net->rate_dwn)); | |||||
errdie(buf_print(&iob, "2:rui%lue", tp->net->rate_up)); | |||||
errdie(buf_print(&iob, "12:seen npiecesi%ue", seen_npieces)); | errdie(buf_print(&iob, "12:seen npiecesi%ue", seen_npieces)); | ||||
errdie(buf_print(&iob, "2:upi%juee", (intmax_t)tp->uploaded)); | errdie(buf_print(&iob, "5:totali%jde", | ||||
(intmax_t)tp->meta.total_length)); | |||||
errdie(buf_print(&iob, "2:upi%juee", (intmax_t)tp->net->uploaded)); | |||||
} | } | ||||
errdie(buf_swrite(&iob, "ee")); | errdie(buf_swrite(&iob, "ee")); | ||||
@@ -59,6 +66,7 @@ cmd_stat(int argc, const char *args, FILE *fp) | |||||
free(iob.buf); | free(iob.buf); | ||||
} | } | ||||
#if 0 | |||||
static void | static void | ||||
cmd_add(int argc, const char *args, FILE *fp) | cmd_add(int argc, const char *args, FILE *fp) | ||||
{ | { | ||||
@@ -144,15 +152,18 @@ cmd_die(int argc, const char *args, FILE *fp) | |||||
btpd_log(BTPD_L_BTPD, "Someone wants me dead.\n"); | btpd_log(BTPD_L_BTPD, "Someone wants me dead.\n"); | ||||
btpd_shutdown(); | btpd_shutdown(); | ||||
} | } | ||||
#endif | |||||
static struct { | static struct { | ||||
const char *name; | const char *name; | ||||
int nlen; | int nlen; | ||||
void (*fun)(int, const char *, FILE *); | void (*fun)(int, const char *, FILE *); | ||||
} cmd_table[] = { | } cmd_table[] = { | ||||
#if 0 | |||||
{ "add", 3, cmd_add }, | { "add", 3, cmd_add }, | ||||
{ "del", 3, cmd_del }, | { "del", 3, cmd_del }, | ||||
{ "die", 3, cmd_die }, | { "die", 3, cmd_die }, | ||||
#endif | |||||
{ "stat", 4, cmd_stat } | { "stat", 4, cmd_stat } | ||||
}; | }; | ||||
@@ -61,8 +61,13 @@ setup_daemon(const char *dir) | |||||
err(1, "Couldn't create library"); | err(1, "Couldn't create library"); | ||||
pidfd = open("pid", O_CREAT|O_WRONLY|O_NONBLOCK|O_EXLOCK, 0666); | pidfd = open("pid", O_CREAT|O_WRONLY|O_NONBLOCK|O_EXLOCK, 0666); | ||||
if (pidfd == -1) | if (pidfd == -1) { | ||||
err(1, "Couldn't open 'pid'"); | if (errno == EAGAIN) | ||||
errx(1, "Another instance of btpd is probably running in %s.", | |||||
dir); | |||||
else | |||||
err(1, "Couldn't open 'pid'"); | |||||
} | |||||
if (btpd_daemon) { | if (btpd_daemon) { | ||||
if (daemon(1, 1) != 0) | if (daemon(1, 1) != 0) | ||||
@@ -82,6 +87,10 @@ static void | |||||
usage(void) | usage(void) | ||||
{ | { | ||||
printf("Usage: btpd [options] [dir]\n" | printf("Usage: btpd [options] [dir]\n" | ||||
"\n" | |||||
"dir:\n" | |||||
"\tThe directory in which to run btpd.\n" | |||||
"\tDefault is '$HOME/.btpd'.\n" | |||||
"\n" | "\n" | ||||
"Options:\n" | "Options:\n" | ||||
"\n" | "\n" | ||||
@@ -97,11 +106,22 @@ usage(void) | |||||
"\tKeep the btpd process in the foregorund and log to std{out,err}.\n" | "\tKeep the btpd process in the foregorund and log to std{out,err}.\n" | ||||
"\tThis option is intended for debugging purposes.\n" | "\tThis option is intended for debugging purposes.\n" | ||||
"\n" | "\n" | ||||
"--downloaders n\n" | |||||
"\tControls the number of simultaneous uploads.\n" | |||||
"\tThe possible values are:\n" | |||||
"\t\tn < -1 : Choose n >= 2 based on --bw-out (default).\n" | |||||
"\t\tn = -1 : Upload to every interested peer.\n" | |||||
"\t\tn = 0 : Dont't upload to anyone.\n" | |||||
"\t\tn > 0 : Upload to at most n peers simultaneosly.\n" | |||||
"\n" | |||||
"--max-peers n\n" | |||||
"\tLimit the amount of peers to n.\n" | |||||
"\n" | |||||
"-p n, --port n\n" | "-p n, --port n\n" | ||||
"\tListen at port n. Default is 6881.\n" | "\tListen at port n. Default is 6881.\n" | ||||
"\n" | "\n" | ||||
"--prealloc n\n" | "--prealloc n\n" | ||||
"\tPreallocate disk space in chunks n kB. Default is 1.\n" | "\tPreallocate disk space in chunks of n kB. Default is 1.\n" | ||||
"\tNote that n will be rounded up to the closest multiple of the\n" | "\tNote that n will be rounded up to the closest multiple of the\n" | ||||
"\ttorrent piece size. If n is zero no preallocation will be done.\n" | "\ttorrent piece size. If n is zero no preallocation will be done.\n" | ||||
"\n" | "\n" | ||||
@@ -118,7 +138,9 @@ static struct option longopts[] = { | |||||
{ "bw-in", required_argument, &longval, 1 }, | { "bw-in", required_argument, &longval, 1 }, | ||||
{ "bw-out", required_argument, &longval, 2 }, | { "bw-out", required_argument, &longval, 2 }, | ||||
{ "prealloc", required_argument, &longval, 3 }, | { "prealloc", required_argument, &longval, 3 }, | ||||
{ "help", no_argument, &longval, 5 }, | { "downloaders", required_argument, &longval, 4 }, | ||||
{ "max-peers", required_argument, &longval, 5 }, | |||||
{ "help", no_argument, &longval, 128 }, | |||||
{ NULL, 0, NULL, 0 } | { NULL, 0, NULL, 0 } | ||||
}; | }; | ||||
@@ -150,6 +172,12 @@ main(int argc, char **argv) | |||||
case 3: | case 3: | ||||
cm_alloc_size = atoi(optarg) * 1024; | cm_alloc_size = atoi(optarg) * 1024; | ||||
break; | break; | ||||
case 4: | |||||
net_max_downloaders = atoi(optarg); | |||||
break; | |||||
case 5: | |||||
net_max_peers = atoi(optarg); | |||||
break; | |||||
default: | default: | ||||
usage(); | usage(); | ||||
} | } | ||||
@@ -626,16 +626,9 @@ net_init(void) | |||||
m_bw_bytes_out = net_bw_limit_out; | m_bw_bytes_out = net_bw_limit_out; | ||||
m_bw_bytes_in = net_bw_limit_in; | m_bw_bytes_in = net_bw_limit_in; | ||||
int nfiles = getdtablesize(); | int safe_fds = min(getdtablesize(), FD_SETSIZE) * 4 / 5; | ||||
if (nfiles <= 20) | if (net_max_peers == 0 || net_max_peers > safe_fds) | ||||
btpd_err("Too few open files allowed (%d). " | net_max_peers = safe_fds; | ||||
"Check \"ulimit -n\"\n", nfiles); | |||||
else if (nfiles < 64) | |||||
btpd_log(BTPD_L_BTPD, | |||||
"You have restricted the number of open files to %d. " | |||||
"More could be beneficial to the download performance.\n", | |||||
nfiles); | |||||
net_max_peers = nfiles - 20; | |||||
int sd; | int sd; | ||||
int flag = 1; | int flag = 1; | ||||
@@ -7,6 +7,7 @@ uint32_t btpd_logmask = BTPD_L_ALL; | |||||
#else | #else | ||||
uint32_t btpd_logmask = BTPD_L_BTPD | BTPD_L_ERROR; | uint32_t btpd_logmask = BTPD_L_BTPD | BTPD_L_ERROR; | ||||
#endif | #endif | ||||
int net_max_downloaders = -2; | |||||
unsigned net_max_peers; | unsigned net_max_peers; | ||||
unsigned net_bw_limit_in; | unsigned net_bw_limit_in; | ||||
unsigned net_bw_limit_out; | unsigned net_bw_limit_out; | ||||
@@ -4,6 +4,7 @@ | |||||
extern short btpd_daemon; | extern short btpd_daemon; | ||||
extern const char *btpd_dir; | extern const char *btpd_dir; | ||||
extern uint32_t btpd_logmask; | extern uint32_t btpd_logmask; | ||||
extern int net_max_downloaders; | |||||
extern unsigned net_max_peers; | extern unsigned net_max_peers; | ||||
extern unsigned net_bw_limit_in; | extern unsigned net_bw_limit_in; | ||||
extern unsigned net_bw_limit_out; | extern unsigned net_bw_limit_out; | ||||
@@ -7,7 +7,7 @@ | |||||
static struct event m_choke_timer; | static struct event m_choke_timer; | ||||
static unsigned m_npeers; | static unsigned m_npeers; | ||||
static struct peer_tq m_peerq = BTPDQ_HEAD_INITIALIZER(m_peerq); | static struct peer_tq m_peerq = BTPDQ_HEAD_INITIALIZER(m_peerq); | ||||
static int m_max_downloaders = 4; | static int m_max_downloaders; | ||||
struct peer_sort { | struct peer_sort { | ||||
struct peer *p; | struct peer *p; | ||||
@@ -32,7 +32,7 @@ rate_cmp(const void *arg1, const void *arg2) | |||||
static void | static void | ||||
choke_do(void) | choke_do(void) | ||||
{ | { | ||||
if (m_max_downloaders == -1) { | if (m_max_downloaders < 0) { | ||||
struct peer *p; | struct peer *p; | ||||
BTPDQ_FOREACH(p, &m_peerq, ul_entry) | BTPDQ_FOREACH(p, &m_peerq, ul_entry) | ||||
if (p->flags & PF_I_CHOKE) | if (p->flags & PF_I_CHOKE) | ||||
@@ -42,7 +42,7 @@ choke_do(void) | |||||
BTPDQ_FOREACH(p, &m_peerq, ul_entry) | BTPDQ_FOREACH(p, &m_peerq, ul_entry) | ||||
if ((p->flags & PF_I_CHOKE) == 0) | if ((p->flags & PF_I_CHOKE) == 0) | ||||
peer_choke(p); | peer_choke(p); | ||||
} else if (m_npeers > 0) { | } else { | ||||
struct peer_sort worthy[m_npeers]; | struct peer_sort worthy[m_npeers]; | ||||
int nworthy = 0; | int nworthy = 0; | ||||
int i = 0; | int i = 0; | ||||
@@ -171,6 +171,21 @@ ul_on_uninterest(struct peer *p) | |||||
void | void | ||||
ul_init(void) | ul_init(void) | ||||
{ | { | ||||
if (net_max_downloaders >= -1) | |||||
m_max_downloaders = net_max_downloaders; | |||||
else { | |||||
if (net_bw_limit_out == 0) | |||||
m_max_downloaders = 8; | |||||
else if (net_bw_limit_out < (10 << 10)) | |||||
m_max_downloaders = 2; | |||||
else if (net_bw_limit_out < (20 << 10)) | |||||
m_max_downloaders = 3; | |||||
else if (net_bw_limit_out < (40 << 10)) | |||||
m_max_downloaders = 4; | |||||
else | |||||
m_max_downloaders = 5 + (net_bw_limit_out / (100 << 10)); | |||||
} | |||||
evtimer_set(&m_choke_timer, choke_cb, NULL); | evtimer_set(&m_choke_timer, choke_cb, NULL); | ||||
evtimer_add(&m_choke_timer, CHOKE_INTERVAL); | evtimer_add(&m_choke_timer, CHOKE_INTERVAL); | ||||
} | } |