characters displayed by btcli.master
@@ -65,26 +65,30 @@ cmd_stat(struct cli *cli, int argc, const char *args) | |||||
buf_print(&iob, "9:ntorrentsi%ue", torrent_count()); | buf_print(&iob, "9:ntorrentsi%ue", torrent_count()); | ||||
buf_swrite(&iob, "8:torrentsl"); | buf_swrite(&iob, "8:torrentsl"); | ||||
BTPDQ_FOREACH(tp, torrent_get_all(), entry) { | BTPDQ_FOREACH(tp, torrent_get_all(), entry) { | ||||
const char *name = torrent_name(tp); | |||||
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->net->piece_count[i] > 0) | if (tp->net->piece_count[i] > 0) | ||||
seen_npieces++; | seen_npieces++; | ||||
buf_print(&iob, "d4:downi%llde", tp->net->downloaded); | |||||
buf_print(&iob, "6:errorsi%ue", tr_errors(tp)); | |||||
buf_swrite(&iob, "4:hash20:"); | |||||
buf_swrite(&iob, "d"); | |||||
buf_print(&iob, "11:content goti%jde", (intmax_t)cm_content(tp)); | |||||
buf_print(&iob, "12:content sizei%jde", | |||||
(intmax_t)tp->meta.total_length); | |||||
buf_print(&iob, "10:downloadedi%llde", tp->net->downloaded); | |||||
buf_swrite(&iob, "9:info hash20:"); | |||||
buf_write(&iob, tp->meta.info_hash, 20); | buf_write(&iob, tp->meta.info_hash, 20); | ||||
buf_print(&iob, "4:havei%jde", (intmax_t)cm_get_size(tp)); | |||||
buf_print(&iob, "6:npeersi%ue", tp->net->npeers); | |||||
buf_print(&iob, "7:npiecesi%ue", tp->meta.npieces); | |||||
buf_print(&iob, "4:path%d:%s", (int)strlen(tp->meta.name), | |||||
tp->meta.name); | |||||
buf_print(&iob, "2:rdi%lue", tp->net->rate_dwn); | |||||
buf_print(&iob, "2:rui%lue", tp->net->rate_up); | |||||
buf_print(&iob, "12:seen npiecesi%ue", seen_npieces); | |||||
buf_print(&iob, "4:name%d:%s", (int)strlen(name), name); | |||||
buf_print(&iob, "5:peersi%ue", tp->net->npeers); | |||||
buf_print(&iob, "10:pieces goti%ue", cm_pieces(tp)); | |||||
buf_print(&iob, "11:pieces seeni%ue", seen_npieces); | |||||
buf_print(&iob, "9:rate downi%lue", tp->net->rate_dwn); | |||||
buf_print(&iob, "7:rate upi%lue", tp->net->rate_up); | |||||
buf_print(&iob, "5:statei%ue", tp->state); | buf_print(&iob, "5:statei%ue", tp->state); | ||||
buf_print(&iob, "5:totali%jde", (intmax_t)tp->meta.total_length); | |||||
buf_print(&iob, "2:upi%lldee", tp->net->uploaded); | |||||
buf_print(&iob, "14:torrent piecesi%ue", tp->meta.npieces); | |||||
buf_print(&iob, "14:tracker errorsi%ue", tr_errors(tp)); | |||||
buf_print(&iob, "8:uploadedi%llde", tp->net->uploaded); | |||||
buf_swrite(&iob, "e"); | |||||
} | } | ||||
buf_swrite(&iob, "ee"); | buf_swrite(&iob, "ee"); | ||||
return write_buffer(cli, &iob); | return write_buffer(cli, &iob); | ||||
@@ -4,6 +4,7 @@ | |||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#include <math.h> | #include <math.h> | ||||
#include <pthread.h> | #include <pthread.h> | ||||
#include <signal.h> | |||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
@@ -434,13 +435,13 @@ cm_full(struct torrent *tp) | |||||
} | } | ||||
off_t | off_t | ||||
cm_get_size(struct torrent *tp) | |||||
cm_content(struct torrent *tp) | |||||
{ | { | ||||
return tp->cm->ncontent_bytes; | return tp->cm->ncontent_bytes; | ||||
} | } | ||||
uint32_t | uint32_t | ||||
cm_get_npieces(struct torrent *tp) | |||||
cm_pieces(struct torrent *tp) | |||||
{ | { | ||||
return tp->cm->npieces_got; | return tp->cm->npieces_got; | ||||
} | } | ||||
@@ -12,11 +12,12 @@ void cm_stop(struct torrent * tp); | |||||
int cm_active(struct torrent *tp); | int cm_active(struct torrent *tp); | ||||
int cm_full(struct torrent *tp); | int cm_full(struct torrent *tp); | ||||
off_t cm_content(struct torrent *tp); | |||||
uint32_t cm_pieces(struct torrent *tp); | |||||
uint8_t *cm_get_piece_field(struct torrent *tp); | uint8_t *cm_get_piece_field(struct torrent *tp); | ||||
uint8_t *cm_get_block_field(struct torrent *tp, uint32_t piece); | uint8_t *cm_get_block_field(struct torrent *tp, uint32_t piece); | ||||
uint32_t cm_get_npieces(struct torrent *tp); | |||||
int cm_has_piece(struct torrent *tp, uint32_t piece); | int cm_has_piece(struct torrent *tp, uint32_t piece); | ||||
int cm_put_bytes(struct torrent *tp, uint32_t piece, uint32_t begin, | int cm_put_bytes(struct torrent *tp, uint32_t piece, uint32_t begin, | ||||
@@ -27,6 +28,4 @@ int cm_get_bytes(struct torrent *tp, uint32_t piece, uint32_t begin, | |||||
void cm_prealloc(struct torrent *tp, uint32_t piece); | void cm_prealloc(struct torrent *tp, uint32_t piece); | ||||
void cm_test_piece(struct torrent *tp, uint32_t piece); | void cm_test_piece(struct torrent *tp, uint32_t piece); | ||||
off_t cm_get_size(struct torrent *tp); | |||||
#endif | #endif |
@@ -106,7 +106,7 @@ static int | |||||
dl_should_enter_endgame(struct net *n) | dl_should_enter_endgame(struct net *n) | ||||
{ | { | ||||
int should; | int should; | ||||
if (cm_get_npieces(n->tp) + n->npcs_busy == n->tp->meta.npieces) { | |||||
if (cm_pieces(n->tp) + n->npcs_busy == n->tp->meta.npieces) { | |||||
should = 1; | should = 1; | ||||
struct piece *pc; | struct piece *pc; | ||||
BTPDQ_FOREACH(pc, &n->getlst, entry) { | BTPDQ_FOREACH(pc, &n->getlst, entry) { | ||||
@@ -121,7 +121,7 @@ nb_create_have(uint32_t index) | |||||
struct net_buf * | struct net_buf * | ||||
nb_create_multihave(struct torrent *tp) | nb_create_multihave(struct torrent *tp) | ||||
{ | { | ||||
uint32_t have_npieces = cm_get_npieces(tp); | |||||
uint32_t have_npieces = cm_pieces(tp); | |||||
struct net_buf *out = nb_create_alloc(NB_MULTIHAVE, 9 * have_npieces); | struct net_buf *out = nb_create_alloc(NB_MULTIHAVE, 9 * have_npieces); | ||||
for (uint32_t i = 0, count = 0; count < have_npieces; i++) { | for (uint32_t i = 0, count = 0; count < have_npieces; i++) { | ||||
if (cm_has_piece(tp, i)) { | if (cm_has_piece(tp, i)) { | ||||
@@ -343,8 +343,8 @@ peer_on_shake(struct peer *p) | |||||
printid[i] = '\0'; | printid[i] = '\0'; | ||||
btpd_log(BTPD_L_MSG, "received shake(%s) from %p\n", printid, p); | btpd_log(BTPD_L_MSG, "received shake(%s) from %p\n", printid, p); | ||||
p->piece_field = btpd_calloc(1, (int)ceil(p->n->tp->meta.npieces / 8.0)); | p->piece_field = btpd_calloc(1, (int)ceil(p->n->tp->meta.npieces / 8.0)); | ||||
if (cm_get_npieces(p->n->tp) > 0) { | |||||
if ((cm_get_npieces(p->n->tp) * 9 < 5 + | |||||
if (cm_pieces(p->n->tp) > 0) { | |||||
if ((cm_pieces(p->n->tp) * 9 < 5 + | |||||
ceil(p->n->tp->meta.npieces / 8.0))) | ceil(p->n->tp->meta.npieces / 8.0))) | ||||
peer_send(p, nb_create_multihave(p->n->tp)); | peer_send(p, nb_create_multihave(p->n->tp)); | ||||
else { | else { | ||||
@@ -199,7 +199,7 @@ tr_send(struct torrent *tp, enum tr_event event) | |||||
"&downloaded=%ju&left=%ju&compact=1%s%s", | "&downloaded=%ju&left=%ju&compact=1%s%s", | ||||
tp->meta.announce, qc, e_hash, e_id, net_port, | tp->meta.announce, qc, e_hash, e_id, net_port, | ||||
(intmax_t)tp->net->uploaded, (intmax_t)tp->net->downloaded, | (intmax_t)tp->net->uploaded, (intmax_t)tp->net->downloaded, | ||||
(intmax_t)tp->meta.total_length - cm_get_size(tp), | |||||
(intmax_t)tp->meta.total_length - cm_content(tp), | |||||
event == TR_EV_EMPTY ? "" : "&event=", m_events[event]); | event == TR_EV_EMPTY ? "" : "&event=", m_events[event]); | ||||
} | } | ||||
@@ -1,5 +1,6 @@ | |||||
#include <stdarg.h> | #include <stdarg.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <time.h> | |||||
#include "btpd.h" | #include "btpd.h" | ||||
@@ -5,6 +5,7 @@ | |||||
#include <errno.h> | #include <errno.h> | ||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#include <getopt.h> | #include <getopt.h> | ||||
#include <inttypes.h> | |||||
#include <limits.h> | #include <limits.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
@@ -46,24 +47,37 @@ handle_ipc_res(enum ipc_code code, const char *target) | |||||
void | void | ||||
print_state_name(struct tpstat *ts) | print_state_name(struct tpstat *ts) | ||||
{ | { | ||||
char statec[] = ">*<U"; | |||||
int state = min(ts->state, 3); | |||||
printf("%c. %s", statec[state], ts->name); | |||||
char c; | |||||
switch (ts->state) { | |||||
case T_STARTING: | |||||
c = '+'; | |||||
break; | |||||
case T_ACTIVE: | |||||
c = ts->pieces_got == ts->torrent_pieces ? 'S' : 'L'; | |||||
break; | |||||
case T_STOPPING: | |||||
c = '-'; | |||||
break; | |||||
default: | |||||
c = 'U'; | |||||
break; | |||||
} | |||||
printf("%c. %s", c, ts->name); | |||||
} | } | ||||
void | void | ||||
print_stat(struct tpstat *cur) | |||||
print_stat(struct tpstat *ts) | |||||
{ | { | ||||
printf("%5.1f%% %6.1fM %7.2fkB/s %6.1fM %7.2fkB/s %4u %5.1f%%", | printf("%5.1f%% %6.1fM %7.2fkB/s %6.1fM %7.2fkB/s %4u %5.1f%%", | ||||
100.0 * cur->have / cur->total, | |||||
(double)cur->downloaded / (1 << 20), | |||||
(double)cur->rate_down / (20 << 10), | |||||
(double)cur->uploaded / (1 << 20), | |||||
(double)cur->rate_up / (20 << 10), | |||||
cur->npeers, | |||||
100.0 * cur->nseen / cur->npieces); | |||||
if (cur->errors > 0) | |||||
printf(" E%u", cur->errors); | |||||
100.0 * ts->content_got / ts->content_size, | |||||
(double)ts->downloaded / (1 << 20), | |||||
(double)ts->rate_down / (20 << 10), | |||||
(double)ts->uploaded / (1 << 20), | |||||
(double)ts->rate_up / (20 << 10), | |||||
ts->peers, | |||||
100.0 * ts->pieces_seen / ts->torrent_pieces); | |||||
if (ts->tr_errors > 0) | |||||
printf(" E%u", ts->tr_errors); | |||||
printf("\n"); | printf("\n"); | ||||
} | } | ||||
@@ -156,7 +170,7 @@ cmd_add(int argc, char **argv) | |||||
&& strcmp(mi->name, mi->files[0].path) == 0))) | && strcmp(mi->name, mi->files[0].path) == 0))) | ||||
snprintf(dpath, PATH_MAX, "%s/%s", bdir, mi->name); | snprintf(dpath, PATH_MAX, "%s/%s", bdir, mi->name); | ||||
else if (dir != NULL) | else if (dir != NULL) | ||||
strlcpy(dpath, bdir, PATH_MAX); | |||||
strncpy(dpath, bdir, PATH_MAX); | |||||
else { | else { | ||||
if (content_link(mi->info_hash, dpath) != 0) { | if (content_link(mi->info_hash, dpath) != 0) { | ||||
warnx("unknown content dir for %s", argv[i]); | warnx("unknown content dir for %s", argv[i]); | ||||
@@ -307,7 +321,6 @@ do_stat(int individual, int seconds, int hash_count, uint8_t (*hashes)[20]) | |||||
struct tpstat tot; | struct tpstat tot; | ||||
again: | again: | ||||
bzero(&tot, sizeof(tot)); | bzero(&tot, sizeof(tot)); | ||||
tot.state = T_ACTIVE; | |||||
if (handle_ipc_res(btpd_stat(ipc, &st), "stat") != IPC_OK) | if (handle_ipc_res(btpd_stat(ipc, &st), "stat") != IPC_OK) | ||||
exit(1); | exit(1); | ||||
for (int i = 0; i < st->ntorrents; i++) { | for (int i = 0; i < st->ntorrents; i++) { | ||||
@@ -324,11 +337,11 @@ again: | |||||
tot.downloaded += cur->downloaded; | tot.downloaded += cur->downloaded; | ||||
tot.rate_up += cur->rate_up; | tot.rate_up += cur->rate_up; | ||||
tot.rate_down += cur->rate_down; | tot.rate_down += cur->rate_down; | ||||
tot.npeers += cur->npeers; | |||||
tot.nseen += cur->nseen; | |||||
tot.npieces += cur->npieces; | |||||
tot.have += cur->have; | |||||
tot.total += cur->total; | |||||
tot.peers += cur->peers; | |||||
tot.pieces_seen += cur->pieces_seen; | |||||
tot.torrent_pieces += cur->torrent_pieces; | |||||
tot.content_got += cur->content_got; | |||||
tot.content_size += cur->content_size; | |||||
if (individual) { | if (individual) { | ||||
print_state_name(cur); | print_state_name(cur); | ||||
printf(":\n"); | printf(":\n"); | ||||
@@ -355,7 +368,7 @@ cmd_stat(int argc, char **argv) | |||||
{ | { | ||||
int ch; | int ch; | ||||
int wflag = 0, iflag = 0, seconds = 0; | int wflag = 0, iflag = 0, seconds = 0; | ||||
uint8_t (*hashes)[20]; | |||||
uint8_t (*hashes)[20] = NULL; | |||||
char *endptr; | char *endptr; | ||||
while ((ch = getopt_long(argc, argv, "iw:", stat_opts, NULL)) != -1) { | while ((ch = getopt_long(argc, argv, "iw:", stat_opts, NULL)) != -1) { | ||||
switch (ch) { | switch (ch) { | ||||
@@ -154,19 +154,20 @@ parse_btstat(const uint8_t *res, struct btstat **out) | |||||
int i = 0; | int i = 0; | ||||
for (const char *tp = benc_first(tlst); tp != NULL; tp = benc_next(tp)) { | for (const char *tp = benc_first(tlst); tp != NULL; tp = benc_next(tp)) { | ||||
struct tpstat *ts = &st->torrents[i]; | struct tpstat *ts = &st->torrents[i]; | ||||
ts->hash = benc_dget_mema(tp, "hash", NULL); | |||||
ts->name = benc_dget_str(tp, "path", NULL); | |||||
ts->hash = benc_dget_mema(tp, "info hash", NULL); | |||||
ts->name = benc_dget_str(tp, "name", NULL); | |||||
ts->state = benc_dget_int(tp, "state"); | ts->state = benc_dget_int(tp, "state"); | ||||
ts->errors = benc_dget_int(tp, "errors"); | |||||
ts->npieces = benc_dget_int(tp, "npieces"); | |||||
ts->nseen = benc_dget_int(tp, "seen npieces"); | |||||
ts->npeers = benc_dget_int(tp, "npeers"); | |||||
ts->downloaded = benc_dget_int(tp, "down"); | |||||
ts->uploaded = benc_dget_int(tp, "up"); | |||||
ts->rate_down = benc_dget_int(tp, "rd"); | |||||
ts->rate_up = benc_dget_int(tp, "ru"); | |||||
ts->have = benc_dget_int(tp, "have"); | |||||
ts->total = benc_dget_int(tp, "total"); | |||||
ts->peers = benc_dget_int(tp, "peers"); | |||||
ts->tr_errors = benc_dget_int(tp, "tracker errors"); | |||||
ts->content_got = benc_dget_int(tp, "content got"); | |||||
ts->content_size = benc_dget_int(tp, "content size"); | |||||
ts->pieces_got = benc_dget_int(tp, "pieces got"); | |||||
ts->pieces_seen = benc_dget_int(tp, "pieces seen"); | |||||
ts->torrent_pieces = benc_dget_int(tp, "torrent pieces"); | |||||
ts->downloaded = benc_dget_int(tp, "downloaded"); | |||||
ts->uploaded = benc_dget_int(tp, "uploaded"); | |||||
ts->rate_down = benc_dget_int(tp, "rate down"); | |||||
ts->rate_up = benc_dget_int(tp, "rate up"); | |||||
i++; | i++; | ||||
} | } | ||||
*out = st; | *out = st; | ||||
@@ -22,12 +22,11 @@ struct btstat { | |||||
uint8_t *hash; | uint8_t *hash; | ||||
char *name; | char *name; | ||||
enum torrent_state state; | enum torrent_state state; | ||||
unsigned errors; | |||||
unsigned npeers; | |||||
uint32_t npieces, nseen; | |||||
off_t have, total; | |||||
long long downloaded, uploaded; | |||||
unsigned tr_errors; | |||||
unsigned peers; | |||||
uint32_t pieces_got, pieces_seen, torrent_pieces; | |||||
off_t content_got, content_size; | |||||
unsigned long long downloaded, uploaded; | |||||
unsigned long rate_up, rate_down; | unsigned long rate_up, rate_down; | ||||
} torrents[]; | } torrents[]; | ||||
}; | }; | ||||