소스 검색

The mega whitespace patch.

Tabs have been converted to spaces and trailing whitespace have been removed.
I have fixed my emacs settings now :P
master
Richard Nyberg 19 년 전
부모
커밋
c285b374f8
28개의 변경된 파일1608개의 추가작업 그리고 1608개의 파일을 삭제
  1. +12
    -12
      btpd/btpd.c
  2. +7
    -7
      btpd/btpd.h
  3. +58
    -58
      btpd/cli_if.c
  4. +53
    -53
      btpd/download.c
  5. +224
    -224
      btpd/download_subr.c
  6. +73
    -73
      btpd/main.c
  7. +242
    -242
      btpd/net.c
  8. +9
    -9
      btpd/net.h
  9. +24
    -24
      btpd/net_buf.c
  10. +13
    -13
      btpd/net_buf.h
  11. +164
    -164
      btpd/peer.c
  12. +12
    -12
      btpd/peer.h
  13. +60
    -60
      btpd/queue.h
  14. +50
    -50
      btpd/torrent.c
  15. +2
    -2
      btpd/torrent.h
  16. +87
    -87
      btpd/tracker_req.c
  17. +6
    -6
      btpd/upload.c
  18. +18
    -18
      btpd/util.c
  19. +125
    -125
      cli/btcli.c
  20. +10
    -10
      cli/btinfo.c
  21. +36
    -36
      cli/btpd_if.c
  22. +1
    -1
      cli/btpd_if.h
  23. +105
    -105
      misc/benc.c
  24. +1
    -1
      misc/benc.h
  25. +100
    -100
      misc/metainfo.c
  26. +80
    -80
      misc/stream.c
  27. +1
    -1
      misc/stream.h
  28. +35
    -35
      misc/subr.c

+ 12
- 12
btpd/btpd.c 파일 보기

@@ -83,15 +83,15 @@ child_cb(int signal, short type, void *arg)
pid_t pid;

while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
if (WIFEXITED(status) || WIFSIGNALED(status)) {
struct child *kid = BTPDQ_FIRST(&m_kids);
while (kid != NULL && kid->pid != pid)
kid = BTPDQ_NEXT(kid, entry);
assert(kid != NULL);
BTPDQ_REMOVE(&m_kids, kid, entry);
kid->cb(kid->pid, kid->arg);
free(kid);
}
if (WIFEXITED(status) || WIFSIGNALED(status)) {
struct child *kid = BTPDQ_FIRST(&m_kids);
while (kid != NULL && kid->pid != pid)
kid = BTPDQ_NEXT(kid, entry);
assert(kid != NULL);
BTPDQ_REMOVE(&m_kids, kid, entry);
kid->cb(kid->pid, kid->arg);
free(kid);
}
}
}

@@ -102,7 +102,7 @@ btpd_add_torrent(struct torrent *tp)
m_ntorrents++;
}

void
void
btpd_del_torrent(struct torrent *tp)
{
BTPDQ_REMOVE(&m_torrents, tp, entry);
@@ -126,7 +126,7 @@ btpd_get_torrent(const uint8_t *hash)
{
struct torrent *tp = BTPDQ_FIRST(&m_torrents);
while (tp != NULL && bcmp(hash, tp->meta.info_hash, 20) != 0)
tp = BTPDQ_NEXT(tp, entry);
tp = BTPDQ_NEXT(tp, entry);
return tp;
}

@@ -145,7 +145,7 @@ btpd_init(void)
m_peer_id[sizeof(BTPD_VERSION) - 1] = '|';
srandom(time(NULL));
for (int i = sizeof(BTPD_VERSION); i < 20; i++)
m_peer_id[i] = rint(random() * 255.0 / RAND_MAX);
m_peer_id[i] = rint(random() * 255.0 / RAND_MAX);

net_init();
ipc_init();


+ 7
- 7
btpd/btpd.h 파일 보기

@@ -30,13 +30,13 @@

#define BTPD_VERSION (PACKAGE_NAME "/" PACKAGE_VERSION)

#define BTPD_L_ALL 0xffffffff
#define BTPD_L_ERROR 0x00000001
#define BTPD_L_TRACKER 0x00000002
#define BTPD_L_CONN 0x00000004
#define BTPD_L_MSG 0x00000008
#define BTPD_L_BTPD 0x00000010
#define BTPD_L_POL 0x00000020
#define BTPD_L_ALL 0xffffffff
#define BTPD_L_ERROR 0x00000001
#define BTPD_L_TRACKER 0x00000002
#define BTPD_L_CONN 0x00000004
#define BTPD_L_MSG 0x00000008
#define BTPD_L_BTPD 0x00000010
#define BTPD_L_POL 0x00000020

void btpd_init(void);



+ 58
- 58
btpd/cli_if.c 파일 보기

@@ -25,7 +25,7 @@ static void
errdie(int error)
{
if (error != 0)
btpd_err("io_buf: %s.\n", strerror(error));
btpd_err("io_buf: %s.\n", strerror(error));
}

static void
@@ -34,7 +34,7 @@ cmd_stat(int argc, const char *args, FILE *fp)
struct torrent *tp;
struct io_buffer iob;
errdie(buf_init(&iob, (1 << 14)));
errdie(buf_swrite(&iob, "d"));
errdie(buf_print(&iob, "6:npeersi%ue", net_npeers));
errdie(buf_print(&iob, "9:ntorrentsi%ue", btpd_get_ntorrents()));
@@ -44,16 +44,16 @@ cmd_stat(int argc, const char *args, FILE *fp)
for (uint32_t i = 0; i < tp->meta.npieces; i++)
if (tp->piece_count[i] > 0)
seen_npieces++;
errdie(buf_print(&iob, "d4:downi%" PRIu64 "e", tp->downloaded));
errdie(buf_swrite(&iob, "4:hash20:"));
errdie(buf_write(&iob, tp->meta.info_hash, 20));
errdie(buf_print(&iob, "12:have npiecesi%ue", tp->have_npieces));
errdie(buf_print(&iob, "6:npeersi%ue", tp->npeers));
errdie(buf_print(&iob, "d4:downi%" PRIu64 "e", tp->downloaded));
errdie(buf_swrite(&iob, "4:hash20:"));
errdie(buf_write(&iob, tp->meta.info_hash, 20));
errdie(buf_print(&iob, "12:have npiecesi%ue", tp->have_npieces));
errdie(buf_print(&iob, "6:npeersi%ue", tp->npeers));
errdie(buf_print(&iob, "7:npiecesi%ue", tp->meta.npieces));
errdie(buf_print(&iob, "4:path%d:%s",
(int)strlen(tp->relpath), tp->relpath));
errdie(buf_print(&iob, "12:seen npiecesi%ue", seen_npieces));
errdie(buf_print(&iob, "2:upi%" PRIu64 "ee", tp->uploaded));
(int)strlen(tp->relpath), tp->relpath));
errdie(buf_print(&iob, "12:seen npiecesi%ue", seen_npieces));
errdie(buf_print(&iob, "2:upi%" PRIu64 "ee", tp->uploaded));
}
errdie(buf_swrite(&iob, "ee"));

@@ -71,33 +71,33 @@ cmd_add(int argc, const char *args, FILE *fp)

errdie(buf_write(&iob, "l", 1));
while (args != NULL) {
size_t plen;
char path[PATH_MAX];
const char *pathp;
if (!benc_isstr(args)) {
free(iob.buf);
return;
}
benc_str(args, &pathp, &plen, &args);
if (plen >= PATH_MAX) {
errdie(buf_print(&iob, "d4:codei%dee", ENAMETOOLONG));
continue;
}
bcopy(pathp, path, plen);
path[plen] = '\0';
btpd_log(BTPD_L_BTPD, "add request for %s.\n", path);
errdie(buf_print(&iob, "d4:codei%dee", torrent_load(path)));
size_t plen;
char path[PATH_MAX];
const char *pathp;
if (!benc_isstr(args)) {
free(iob.buf);
return;
}
benc_str(args, &pathp, &plen, &args);
if (plen >= PATH_MAX) {
errdie(buf_print(&iob, "d4:codei%dee", ENAMETOOLONG));
continue;
}
bcopy(pathp, path, plen);
path[plen] = '\0';
btpd_log(BTPD_L_BTPD, "add request for %s.\n", path);
errdie(buf_print(&iob, "d4:codei%dee", torrent_load(path)));
}
errdie(buf_write(&iob, "e", 1));

uint32_t len = iob.buf_off;
fwrite(&len, sizeof(len), 1, fp);
fwrite(iob.buf, 1, iob.buf_off, fp);
free(iob.buf);
free(iob.buf);
}

static void
@@ -105,7 +105,7 @@ cmd_del(int argc, const char *args, FILE *fp)
{
struct io_buffer iob;
errdie(buf_init(&iob, (1 << 10)));
errdie(buf_swrite(&iob, "l"));

while (args != NULL) {
@@ -114,18 +114,18 @@ cmd_del(int argc, const char *args, FILE *fp)
struct torrent *tp;

if (!benc_isstr(args) ||
benc_str(args, &hash, &len, &args) != 0 || len != 20) {
free(iob.buf);
benc_str(args, &hash, &len, &args) != 0 || len != 20) {
free(iob.buf);
return;
}

tp = btpd_get_torrent(hash);
if (tp != NULL) {
btpd_log(BTPD_L_BTPD, "del request for %s.\n", tp->relpath);
btpd_log(BTPD_L_BTPD, "del request for %s.\n", tp->relpath);
torrent_unload(tp);
errdie(buf_swrite(&iob, "d4:codei0ee"));
} else {
btpd_log(BTPD_L_BTPD, "del request didn't match.\n");
btpd_log(BTPD_L_BTPD, "del request didn't match.\n");
errdie(buf_print(&iob, "d4:codei%dee", ENOENT));
}
}
@@ -154,10 +154,10 @@ static struct {
int nlen;
void (*fun)(int, const char *, FILE *);
} cmd_table[] = {
{ "add", 3, cmd_add },
{ "del", 3, cmd_del },
{ "die", 3, cmd_die },
{ "stat", 4, cmd_stat }
{ "add", 3, cmd_add },
{ "del", 3, cmd_del },
{ "die", 3, cmd_die },
{ "stat", 4, cmd_stat }
};

static int ncmds = sizeof(cmd_table) / sizeof(cmd_table[0]);
@@ -208,20 +208,20 @@ client_connection_cb(int sd, short type, void *arg)
FILE *fp;

if ((nsd = accept(sd, NULL, NULL)) < 0) {
if (errno == EWOULDBLOCK || errno == ECONNABORTED)
return;
else
if (errno == EWOULDBLOCK || errno == ECONNABORTED)
return;
else
btpd_err("client accept: %s\n", strerror(errno));
}

if ((errno = set_blocking(nsd)) != 0)
btpd_err("set_blocking: %s.\n", strerror(errno));
btpd_err("set_blocking: %s.\n", strerror(errno));

if ((fp = fdopen(nsd, "r+")) == NULL) {
close(nsd);
return;
close(nsd);
return;
}
do_ipc(fp);

fclose(fp);
@@ -236,25 +236,25 @@ ipc_init(void)

addr.sun_family = PF_UNIX;
if (snprintf(addr.sun_path, psiz, "%s/sock", btpd_dir) >= psiz)
btpd_err("'%s/sock' is too long.\n", btpd_dir);
btpd_err("'%s/sock' is too long.\n", btpd_dir);
if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
btpd_err("sock: %s\n", strerror(errno));
btpd_err("sock: %s\n", strerror(errno));
if (bind(sd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
if (errno == EADDRINUSE) {
unlink(addr.sun_path);
if (bind(sd, (struct sockaddr *)&addr, sizeof(addr)) != 0)
btpd_err("bind: %s\n", strerror(errno));
} else
btpd_err("bind: %s\n", strerror(errno));
if (errno == EADDRINUSE) {
unlink(addr.sun_path);
if (bind(sd, (struct sockaddr *)&addr, sizeof(addr)) != 0)
btpd_err("bind: %s\n", strerror(errno));
} else
btpd_err("bind: %s\n", strerror(errno));
}

if (chmod(addr.sun_path, 0600) == -1)
btpd_err("chmod: %s (%s).\n", addr.sun_path, strerror(errno));
btpd_err("chmod: %s (%s).\n", addr.sun_path, strerror(errno));
listen(sd, 4);
set_nonblocking(sd);

event_set(&m_cli_incoming, sd, EV_READ | EV_PERSIST,
client_connection_cb, NULL);
client_connection_cb, NULL);
event_add(&m_cli_incoming, NULL);
}

+ 53
- 53
btpd/download.c 파일 보기

@@ -18,14 +18,14 @@ dl_stop(struct torrent *tp)
peer = BTPDQ_FIRST(&tp->peers);
while (peer != NULL) {
struct peer *next = BTPDQ_NEXT(peer, p_entry);
BTPDQ_REMOVE(&tp->peers, peer, p_entry);
BTPDQ_INSERT_TAIL(&net_unattached, peer, p_entry);
BTPDQ_REMOVE(&tp->peers, peer, p_entry);
BTPDQ_INSERT_TAIL(&net_unattached, peer, p_entry);
peer->flags &= ~PF_ATTACHED;
peer = next;
}

while ((piece = BTPDQ_FIRST(&tp->getlst)) != NULL)
piece_free(piece);
piece_free(piece);
}

/*
@@ -40,24 +40,24 @@ dl_on_piece_ann(struct peer *p, uint32_t index)
struct torrent *tp = p->tp;
tp->piece_count[index]++;
if (has_bit(tp->piece_field, index))
return;
return;
struct piece *pc = dl_find_piece(tp, index);
if (tp->endgame) {
assert(pc != NULL);
peer_want(p, index);
if (!peer_chokes(p) && !peer_laden(p))
dl_assign_requests_eg(p);
assert(pc != NULL);
peer_want(p, index);
if (!peer_chokes(p) && !peer_laden(p))
dl_assign_requests_eg(p);
} else if (pc == NULL) {
peer_want(p, index);
if (!peer_chokes(p) && !peer_laden(p)) {
pc = dl_new_piece(tp, index);
if (pc != NULL)
dl_piece_assign_requests(pc, p);
}
peer_want(p, index);
if (!peer_chokes(p) && !peer_laden(p)) {
pc = dl_new_piece(tp, index);
if (pc != NULL)
dl_piece_assign_requests(pc, p);
}
} else if (!piece_full(pc)) {
peer_want(p, index);
if (!peer_chokes(p) && !peer_laden(p))
dl_piece_assign_requests(pc, p);
peer_want(p, index);
if (!peer_chokes(p) && !peer_laden(p))
dl_piece_assign_requests(pc, p);
}
}

@@ -67,11 +67,11 @@ dl_on_download(struct peer *p)
assert(peer_wanted(p));
struct torrent *tp = p->tp;
if (tp->endgame) {
dl_assign_requests_eg(p);
dl_assign_requests_eg(p);
} else {
unsigned count = dl_assign_requests(p);
if (count == 0 && !p->tp->endgame) // We may have entered end game.
assert(!peer_wanted(p) || peer_laden(p));
unsigned count = dl_assign_requests(p);
if (count == 0 && !p->tp->endgame) // We may have entered end game.
assert(!peer_wanted(p) || peer_laden(p));
}
}

@@ -79,23 +79,23 @@ void
dl_on_unchoke(struct peer *p)
{
if (peer_wanted(p))
dl_on_download(p);
dl_on_download(p);
}

void
dl_on_undownload(struct peer *p)
{
if (!p->tp->endgame)
dl_unassign_requests(p);
dl_unassign_requests(p);
else
dl_unassign_requests_eg(p);
dl_unassign_requests_eg(p);
}

void
dl_on_choke(struct peer *p)
{
if (p->nreqs_out > 0)
dl_on_undownload(p);
dl_on_undownload(p);
}

/**
@@ -115,21 +115,21 @@ dl_on_ok_piece(struct piece *pc)

struct net_buf *have = nb_create_have(pc->index);
BTPDQ_FOREACH(p, &tp->peers, p_entry)
peer_send(p, have);
peer_send(p, have);

if (tp->endgame)
BTPDQ_FOREACH(p, &tp->peers, p_entry)
if (peer_has(p, pc->index))
peer_unwant(p, pc->index);
BTPDQ_FOREACH(p, &tp->peers, p_entry)
if (peer_has(p, pc->index))
peer_unwant(p, pc->index);

assert(pc->nreqs == 0);
piece_free(pc);

if (torrent_has_all(tp)) {
btpd_log(BTPD_L_BTPD, "Finished: %s.\n", tp->relpath);
tracker_req(tp, TR_COMPLETED);
BTPDQ_FOREACH(p, &tp->peers, p_entry)
assert(p->nwant == 0);
btpd_log(BTPD_L_BTPD, "Finished: %s.\n", tp->relpath);
tracker_req(tp, TR_COMPLETED);
BTPDQ_FOREACH(p, &tp->peers, p_entry)
assert(p->nwant == 0);
}
}

@@ -145,21 +145,21 @@ dl_on_bad_piece(struct piece *pc)
pc->index, tp->relpath);

for (uint32_t i = 0; i < pc->nblocks; i++) {
clear_bit(pc->down_field, i);
clear_bit(pc->have_field, i);
clear_bit(pc->down_field, i);
clear_bit(pc->have_field, i);
}
pc->ngot = 0;
pc->nbusy = 0;
msync(tp->imem, tp->isiz, MS_ASYNC);

if (tp->endgame) {
struct peer *p;
BTPDQ_FOREACH(p, &tp->peers, p_entry) {
if (peer_has(p, pc->index) && peer_leech_ok(p) && !peer_laden(p))
dl_assign_requests_eg(p);
}
struct peer *p;
BTPDQ_FOREACH(p, &tp->peers, p_entry) {
if (peer_has(p, pc->index) && peer_leech_ok(p) && !peer_laden(p))
dl_assign_requests_eg(p);
}
} else
dl_on_piece_unfull(pc); // XXX: May get bad data again.
dl_on_piece_unfull(pc); // XXX: May get bad data again.
}

void
@@ -186,14 +186,14 @@ dl_on_lost_peer(struct peer *p)
tp->piece_count[i]--;

if (p->nreqs_out > 0)
dl_on_undownload(p);
dl_on_undownload(p);
#if 0
struct piece *pc = BTPDQ_FIRST(&tp->getlst);
while (pc != NULL) {
struct piece *next = BTPDQ_NEXT(pc, entry);
if (peer_has(p, pc->index) && tp->piece_count[pc->index] == 0)
dl_on_peerless_piece(pc);
pc = next;
struct piece *next = BTPDQ_NEXT(pc, entry);
if (peer_has(p, pc->index) && tp->piece_count[pc->index] == 0)
dl_on_peerless_piece(pc);
pc = next;
}
#endif
}
@@ -238,12 +238,12 @@ dl_on_block(struct peer *p, struct block_request *req,
BTPDQ_REMOVE(&blk->reqs, req, blk_entry);
free(req);
pc->nreqs--;
// XXX: Needs to be looked at if we introduce snubbing.
clear_bit(pc->down_field, begin / PIECE_BLOCKLEN);
pc->nbusy--;
if (pc->ngot == pc->nblocks)
dl_on_piece(pc);
if (peer_leech_ok(p) && !peer_laden(p))
dl_assign_requests(p);
// XXX: Needs to be looked at if we introduce snubbing.
clear_bit(pc->down_field, begin / PIECE_BLOCKLEN);
pc->nbusy--;
if (pc->ngot == pc->nblocks)
dl_on_piece(pc);
if (peer_leech_ok(p) && !peer_laden(p))
dl_assign_requests(p);
}
}

+ 224
- 224
btpd/download_subr.c 파일 보기

@@ -33,7 +33,7 @@ static struct piece *
piece_alloc(struct torrent *tp, uint32_t index)
{
assert(!has_bit(tp->busy_field, index)
&& tp->npcs_busy < tp->meta.npieces);
&& tp->npcs_busy < tp->meta.npieces);
struct piece *pc;
size_t mem, field, blocks;
unsigned nblocks;
@@ -48,8 +48,8 @@ piece_alloc(struct torrent *tp, uint32_t index)
pc->tp = tp;
pc->down_field = (uint8_t *)(pc + 1);
pc->have_field =
tp->block_field +
index * (size_t)ceil(tp->meta.piece_length / (double)(1 << 17));
tp->block_field +
index * (size_t)ceil(tp->meta.piece_length / (double)(1 << 17));

pc->index = index;
pc->nblocks = nblocks;
@@ -58,19 +58,19 @@ piece_alloc(struct torrent *tp, uint32_t index)
pc->next_block = 0;

for (unsigned i = 0; i < nblocks; i++)
if (has_bit(pc->have_field, i))
pc->ngot++;
if (has_bit(pc->have_field, i))
pc->ngot++;

pc->blocks = (struct block *)(pc->down_field + field);
for (unsigned i = 0; i < nblocks; i++) {
uint32_t start = i * PIECE_BLOCKLEN;
uint32_t len = torrent_block_size(pc, i);
struct block *blk = &pc->blocks[i];
blk->pc = pc;
BTPDQ_INIT(&blk->reqs);
blk->msg = nb_create_request(index, start, len);
nb_hold(blk->msg);
}
uint32_t start = i * PIECE_BLOCKLEN;
uint32_t len = torrent_block_size(pc, i);
struct block *blk = &pc->blocks[i];
blk->pc = pc;
BTPDQ_INIT(&blk->reqs);
blk->msg = nb_create_request(index, start, len);
nb_hold(blk->msg);
}

tp->npcs_busy++;
set_bit(tp->busy_field, index);
@@ -87,13 +87,13 @@ piece_free(struct piece *pc)
clear_bit(tp->busy_field, pc->index);
BTPDQ_REMOVE(&pc->tp->getlst, pc, entry);
for (unsigned i = 0; i < pc->nblocks; i++) {
struct block_request *req = BTPDQ_FIRST(&pc->blocks[i].reqs);
while (req != NULL) {
struct block_request *next = BTPDQ_NEXT(req, blk_entry);
free(req);
req = next;
}
nb_drop(pc->blocks[i].msg);
struct block_request *req = BTPDQ_FIRST(&pc->blocks[i].reqs);
while (req != NULL) {
struct block_request *next = BTPDQ_NEXT(req, blk_entry);
free(req);
req = next;
}
nb_drop(pc->blocks[i].msg);
}
free(pc);
}
@@ -109,16 +109,16 @@ dl_should_enter_endgame(struct torrent *tp)
{
int should;
if (tp->have_npieces + tp->npcs_busy == tp->meta.npieces) {
should = 1;
struct piece *pc;
BTPDQ_FOREACH(pc, &tp->getlst, entry) {
if (!piece_full(pc)) {
should = 0;
break;
}
}
should = 1;
struct piece *pc;
BTPDQ_FOREACH(pc, &tp->getlst, entry) {
if (!piece_full(pc)) {
should = 0;
break;
}
}
} else
should = 0;
should = 0;
return should;
}

@@ -127,19 +127,19 @@ dl_piece_insert_eg(struct piece *pc)
{
struct piece_tq *getlst = &pc->tp->getlst;
if (pc->nblocks == pc->ngot)
BTPDQ_INSERT_TAIL(getlst, pc, entry);
BTPDQ_INSERT_TAIL(getlst, pc, entry);
else {
unsigned r = pc->nreqs / (pc->nblocks - pc->ngot);
struct piece *it;
BTPDQ_FOREACH(it, getlst, entry) {
if ((it->nblocks == it->ngot
|| r < it->nreqs / (it->nblocks - it->ngot))) {
BTPDQ_INSERT_BEFORE(it, pc, entry);
break;
}
}
if (it == NULL)
BTPDQ_INSERT_TAIL(getlst, pc, entry);
unsigned r = pc->nreqs / (pc->nblocks - pc->ngot);
struct piece *it;
BTPDQ_FOREACH(it, getlst, entry) {
if ((it->nblocks == it->ngot
|| r < it->nreqs / (it->nblocks - it->ngot))) {
BTPDQ_INSERT_BEFORE(it, pc, entry);
break;
}
}
if (it == NULL)
BTPDQ_INSERT_TAIL(getlst, pc, entry);
}
}

@@ -163,25 +163,25 @@ dl_enter_endgame(struct torrent *tp)

pi = 0;
BTPDQ_FOREACH(pc, &tp->getlst, entry) {
for (unsigned i = 0; i < pc->nblocks; i++)
clear_bit(pc->down_field, i);
pc->nbusy = 0;
pcs[pi] = pc;
pi++;
for (unsigned i = 0; i < pc->nblocks; i++)
clear_bit(pc->down_field, i);
pc->nbusy = 0;
pcs[pi] = pc;
pi++;
}
BTPDQ_INIT(&tp->getlst);
while (pi > 0) {
pi--;
dl_piece_insert_eg(pcs[pi]);
pi--;
dl_piece_insert_eg(pcs[pi]);
}
BTPDQ_FOREACH(p, &tp->peers, p_entry) {
assert(p->nwant == 0);
BTPDQ_FOREACH(pc, &tp->getlst, entry) {
if (peer_has(p, pc->index))
peer_want(p, pc->index);
}
if (p->nwant > 0 && peer_leech_ok(p) && !peer_laden(p))
dl_assign_requests_eg(p);
assert(p->nwant == 0);
BTPDQ_FOREACH(pc, &tp->getlst, entry) {
if (peer_has(p, pc->index))
peer_want(p, pc->index);
}
if (p->nwant > 0 && peer_leech_ok(p) && !peer_laden(p))
dl_assign_requests_eg(p);
}
}

@@ -190,8 +190,8 @@ dl_find_piece(struct torrent *tp, uint32_t index)
{
struct piece *pc;
BTPDQ_FOREACH(pc, &tp->getlst, entry)
if (pc->index == index)
break;
if (pc->index == index)
break;
return pc;
}

@@ -199,31 +199,31 @@ static int
test_hash(struct torrent *tp, uint8_t *hash, unsigned long index)
{
if (tp->meta.piece_hash != NULL)
return memcmp(hash, tp->meta.piece_hash[index], SHA_DIGEST_LENGTH);
return memcmp(hash, tp->meta.piece_hash[index], SHA_DIGEST_LENGTH);
else {
char piece_hash[SHA_DIGEST_LENGTH];
int fd;
int bufi;
int err;
err = vopen(&fd, O_RDONLY, "%s/torrent", tp->relpath);
if (err != 0)
btpd_err("test_hash: %s\n", strerror(err));
err = lseek(fd, tp->meta.pieces_off + index * SHA_DIGEST_LENGTH,
SEEK_SET);
if (err < 0)
btpd_err("test_hash: %s\n", strerror(errno));
bufi = 0;
while (bufi < SHA_DIGEST_LENGTH) {
ssize_t nread =
read(fd, piece_hash + bufi, SHA_DIGEST_LENGTH - bufi);
bufi += nread;
}
close(fd);
return memcmp(hash, piece_hash, SHA_DIGEST_LENGTH);
char piece_hash[SHA_DIGEST_LENGTH];
int fd;
int bufi;
int err;
err = vopen(&fd, O_RDONLY, "%s/torrent", tp->relpath);
if (err != 0)
btpd_err("test_hash: %s\n", strerror(err));
err = lseek(fd, tp->meta.pieces_off + index * SHA_DIGEST_LENGTH,
SEEK_SET);
if (err < 0)
btpd_err("test_hash: %s\n", strerror(errno));
bufi = 0;
while (bufi < SHA_DIGEST_LENGTH) {
ssize_t nread =
read(fd, piece_hash + bufi, SHA_DIGEST_LENGTH - bufi);
bufi += nread;
}
close(fd);
return memcmp(hash, piece_hash, SHA_DIGEST_LENGTH);
}
}

@@ -244,18 +244,18 @@ torrent_test_piece(struct piece *pc)
off_t plen = torrent_piece_size(tp, pc->index);

if ((bts = bts_open_ro(&tp->meta, pc->index * tp->meta.piece_length,
ro_fd_cb, tp)) == NULL)
btpd_err("Out of memory.\n");
ro_fd_cb, tp)) == NULL)
btpd_err("Out of memory.\n");

if ((err = bts_sha(bts, plen, hash)) != 0)
btpd_err("Ouch! %s\n", strerror(err));
btpd_err("Ouch! %s\n", strerror(err));

bts_close_ro(bts);

if (test_hash(tp, hash, pc->index) == 0)
dl_on_ok_piece(pc);
dl_on_ok_piece(pc);
else
dl_on_bad_piece(pc);
dl_on_bad_piece(pc);
}

void
@@ -268,7 +268,7 @@ static int
dl_piece_startable(struct peer *p, uint32_t index)
{
return peer_has(p, index) && !has_bit(p->tp->piece_field, index)
&& !has_bit(p->tp->busy_field, index);
&& !has_bit(p->tp->busy_field, index);
}

/*
@@ -287,39 +287,39 @@ dl_choose_rarest(struct peer *p, uint32_t *res)
assert(tp->endgame == 0);

for (i = 0; i < tp->meta.npieces && !dl_piece_startable(p, i); i++)
;
;

if (i == tp->meta.npieces)
return ENOENT;
return ENOENT;
uint32_t min_i = i;
uint32_t min_c = 1;
for(i++; i < tp->meta.npieces; i++) {
if (dl_piece_startable(p, i)) {
if (tp->piece_count[i] == tp->piece_count[min_i])
min_c++;
else if (tp->piece_count[i] < tp->piece_count[min_i]) {
min_i = i;
min_c = 1;
}
}
if (dl_piece_startable(p, i)) {
if (tp->piece_count[i] == tp->piece_count[min_i])
min_c++;
else if (tp->piece_count[i] < tp->piece_count[min_i]) {
min_i = i;
min_c = 1;
}
}
}
if (min_c > 1) {
min_c = 1 + rint((double)random() * (min_c - 1) / RAND_MAX);
for (i = min_i; min_c > 0; i++) {
if (dl_piece_startable(p, i)
&& tp->piece_count[i] == tp->piece_count[min_i]) {
min_c--;
min_i = i;
}
}
min_c = 1 + rint((double)random() * (min_c - 1) / RAND_MAX);
for (i = min_i; min_c > 0; i++) {
if (dl_piece_startable(p, i)
&& tp->piece_count[i] == tp->piece_count[min_i]) {
min_c--;
min_i = i;
}
}
}
*res = min_i;
return 0;
}

/*
* Called from either dl_piece_assign_requests or dl_new_piece,
* Called from either dl_piece_assign_requests or dl_new_piece,
* when a pice becomes full. The wanted level of the peers
* that has this piece will be decreased. This function is
* the only one that may trigger end game.
@@ -329,11 +329,11 @@ dl_on_piece_full(struct piece *pc)
{
struct peer *p;
BTPDQ_FOREACH(p, &pc->tp->peers, p_entry) {
if (peer_has(p, pc->index))
peer_unwant(p, pc->index);
if (peer_has(p, pc->index))
peer_unwant(p, pc->index);
}
if (dl_should_enter_endgame(pc->tp))
dl_enter_endgame(pc->tp);
dl_enter_endgame(pc->tp);
}

/*
@@ -351,13 +351,13 @@ dl_new_piece(struct torrent *tp, uint32_t index)
btpd_log(BTPD_L_POL, "Started on piece %u.\n", index);
struct piece *pc = piece_alloc(tp, index);
if (pc->ngot == pc->nblocks) {
dl_on_piece_full(pc);
dl_on_piece(pc);
if (dl_should_enter_endgame(tp))
dl_enter_endgame(tp);
return NULL;
dl_on_piece_full(pc);
dl_on_piece(pc);
if (dl_should_enter_endgame(tp))
dl_enter_endgame(tp);
return NULL;
} else
return pc;
return pc;
}

/*
@@ -374,13 +374,13 @@ dl_on_piece_unfull(struct piece *pc)
struct peer *p;
assert(!piece_full(pc) && tp->endgame == 0);
BTPDQ_FOREACH(p, &tp->peers, p_entry)
if (peer_has(p, pc->index))
peer_want(p, pc->index);
if (peer_has(p, pc->index))
peer_want(p, pc->index);
p = BTPDQ_FIRST(&tp->peers);
while (p != NULL && !piece_full(pc)) {
if (peer_leech_ok(p) && !peer_laden(p))
dl_piece_assign_requests(pc, p); // Cannot provoke end game here.
p = BTPDQ_NEXT(p, p_entry);
if (peer_leech_ok(p) && !peer_laden(p))
dl_piece_assign_requests(pc, p); // Cannot provoke end game here.
p = BTPDQ_NEXT(p, p_entry);
}
}

@@ -400,27 +400,27 @@ dl_piece_assign_requests(struct piece *pc, struct peer *p)
assert(!piece_full(pc) && !peer_laden(p));
unsigned count = 0;
do {
while ((has_bit(pc->have_field, pc->next_block)
|| has_bit(pc->down_field, pc->next_block)))
INCNEXTBLOCK(pc);
struct block *blk = &pc->blocks[pc->next_block];
struct block_request *req = btpd_malloc(sizeof(*req));
req->p = p;
req->blk = blk;
BTPDQ_INSERT_TAIL(&blk->reqs, req, blk_entry);
peer_request(p, req);
set_bit(pc->down_field, pc->next_block);
pc->nbusy++;
pc->nreqs++;
count++;
INCNEXTBLOCK(pc);
while ((has_bit(pc->have_field, pc->next_block)
|| has_bit(pc->down_field, pc->next_block)))
INCNEXTBLOCK(pc);
struct block *blk = &pc->blocks[pc->next_block];
struct block_request *req = btpd_malloc(sizeof(*req));
req->p = p;
req->blk = blk;
BTPDQ_INSERT_TAIL(&blk->reqs, req, blk_entry);
peer_request(p, req);
set_bit(pc->down_field, pc->next_block);
pc->nbusy++;
pc->nreqs++;
count++;
INCNEXTBLOCK(pc);
} while (!piece_full(pc) && !peer_laden(p));

if (piece_full(pc))
dl_on_piece_full(pc);
dl_on_piece_full(pc);

return count;
}
@@ -444,24 +444,24 @@ dl_assign_requests(struct peer *p)
struct torrent *tp = p->tp;
unsigned count = 0;
BTPDQ_FOREACH(pc, &tp->getlst, entry) {
if (piece_full(pc) || !peer_has(p, pc->index))
continue;
count += dl_piece_assign_requests(pc, p);
if (tp->endgame)
break;
if (!piece_full(pc))
assert(peer_laden(p));
if (peer_laden(p))
break;
if (piece_full(pc) || !peer_has(p, pc->index))
continue;
count += dl_piece_assign_requests(pc, p);
if (tp->endgame)
break;
if (!piece_full(pc))
assert(peer_laden(p));
if (peer_laden(p))
break;
}
while (!peer_laden(p) && !tp->endgame) {
uint32_t index;
if (dl_choose_rarest(p, &index) == 0) {
pc = dl_new_piece(tp, index);
if (pc != NULL)
count += dl_piece_assign_requests(pc, p);
} else
break;
uint32_t index;
if (dl_choose_rarest(p, &index) == 0) {
pc = dl_new_piece(tp, index);
if (pc != NULL)
count += dl_piece_assign_requests(pc, p);
} else
break;
}
return count;
}
@@ -470,32 +470,32 @@ void
dl_unassign_requests(struct peer *p)
{
while (p->nreqs_out > 0) {
struct block_request *req = BTPDQ_FIRST(&p->my_reqs);
struct piece *pc = req->blk->pc;
int was_full = piece_full(pc);
while (req != NULL) {
struct block_request *next = BTPDQ_NEXT(req, p_entry);
uint32_t blki = nb_get_begin(req->blk->msg) / PIECE_BLOCKLEN;
struct block *blk = req->blk;
// XXX: Needs to be looked at if we introduce snubbing.
assert(has_bit(pc->down_field, blki));
clear_bit(pc->down_field, blki);
pc->nbusy--;
BTPDQ_REMOVE(&p->my_reqs, req, p_entry);
p->nreqs_out--;
BTPDQ_REMOVE(&blk->reqs, req, blk_entry);
free(req);
pc->nreqs--;
while (next != NULL && next->blk->pc != pc)
next = BTPDQ_NEXT(next, p_entry);
req = next;
}
if (was_full && !piece_full(pc))
dl_on_piece_unfull(pc);
struct block_request *req = BTPDQ_FIRST(&p->my_reqs);
struct piece *pc = req->blk->pc;
int was_full = piece_full(pc);
while (req != NULL) {
struct block_request *next = BTPDQ_NEXT(req, p_entry);
uint32_t blki = nb_get_begin(req->blk->msg) / PIECE_BLOCKLEN;
struct block *blk = req->blk;
// XXX: Needs to be looked at if we introduce snubbing.
assert(has_bit(pc->down_field, blki));
clear_bit(pc->down_field, blki);
pc->nbusy--;
BTPDQ_REMOVE(&p->my_reqs, req, p_entry);
p->nreqs_out--;
BTPDQ_REMOVE(&blk->reqs, req, blk_entry);
free(req);
pc->nreqs--;
while (next != NULL && next->blk->pc != pc)
next = BTPDQ_NEXT(next, p_entry);
req = next;
}
if (was_full && !piece_full(pc))
dl_on_piece_unfull(pc);
}
assert(BTPDQ_EMPTY(&p->my_reqs));
}
@@ -505,18 +505,18 @@ dl_piece_assign_requests_eg(struct piece *pc, struct peer *p)
{
unsigned first_block = pc->next_block;
do {
if ((has_bit(pc->have_field, pc->next_block)
|| peer_requested(p, &pc->blocks[pc->next_block]))) {
INCNEXTBLOCK(pc);
continue;
}
struct block_request *req = btpd_calloc(1, sizeof(*req));
req->blk = &pc->blocks[pc->next_block];
req->p = p;
BTPDQ_INSERT_TAIL(&pc->blocks[pc->next_block].reqs, req, blk_entry);
pc->nreqs++;
INCNEXTBLOCK(pc);
peer_request(p, req);
if ((has_bit(pc->have_field, pc->next_block)
|| peer_requested(p, &pc->blocks[pc->next_block]))) {
INCNEXTBLOCK(pc);
continue;
}
struct block_request *req = btpd_calloc(1, sizeof(*req));
req->blk = &pc->blocks[pc->next_block];
req->p = p;
BTPDQ_INSERT_TAIL(&pc->blocks[pc->next_block].reqs, req, blk_entry);
pc->nreqs++;
INCNEXTBLOCK(pc);
peer_request(p, req);
} while (!peer_laden(p) && pc->next_block != first_block);
}

@@ -530,20 +530,20 @@ dl_assign_requests_eg(struct peer *p)

struct piece *pc = BTPDQ_FIRST(&tp->getlst);
while (!peer_laden(p) && pc != NULL) {
struct piece *next = BTPDQ_NEXT(pc, entry);
if (peer_has(p, pc->index) && pc->nblocks != pc->ngot) {
dl_piece_assign_requests_eg(pc, p);
BTPDQ_REMOVE(&tp->getlst, pc, entry);
BTPDQ_INSERT_HEAD(&tmp, pc, entry);
}
pc = next;
struct piece *next = BTPDQ_NEXT(pc, entry);
if (peer_has(p, pc->index) && pc->nblocks != pc->ngot) {
dl_piece_assign_requests_eg(pc, p);
BTPDQ_REMOVE(&tp->getlst, pc, entry);
BTPDQ_INSERT_HEAD(&tmp, pc, entry);
}
pc = next;
}

pc = BTPDQ_FIRST(&tmp);
while (pc != NULL) {
struct piece *next = BTPDQ_NEXT(pc, entry);
dl_piece_insert_eg(pc);
pc = next;
struct piece *next = BTPDQ_NEXT(pc, entry);
dl_piece_insert_eg(pc);
pc = next;
}
}

@@ -556,31 +556,31 @@ dl_unassign_requests_eg(struct peer *p)
BTPDQ_INIT(&tmp);

while (p->nreqs_out > 0) {
req = BTPDQ_FIRST(&p->my_reqs);
pc = req->blk->pc;
BTPDQ_REMOVE(&pc->tp->getlst, pc, entry);
BTPDQ_INSERT_HEAD(&tmp, pc, entry);
while (req != NULL) {
struct block_request *next = BTPDQ_NEXT(req, p_entry);
BTPDQ_REMOVE(&p->my_reqs, req, p_entry);
p->nreqs_out--;
BTPDQ_REMOVE(&req->blk->reqs, req, blk_entry);
free(req);
pc->nreqs--;
while (next != NULL && next->blk->pc != pc)
next = BTPDQ_NEXT(next, p_entry);
req = next;
}
req = BTPDQ_FIRST(&p->my_reqs);
pc = req->blk->pc;
BTPDQ_REMOVE(&pc->tp->getlst, pc, entry);
BTPDQ_INSERT_HEAD(&tmp, pc, entry);
while (req != NULL) {
struct block_request *next = BTPDQ_NEXT(req, p_entry);
BTPDQ_REMOVE(&p->my_reqs, req, p_entry);
p->nreqs_out--;
BTPDQ_REMOVE(&req->blk->reqs, req, blk_entry);
free(req);
pc->nreqs--;
while (next != NULL && next->blk->pc != pc)
next = BTPDQ_NEXT(next, p_entry);
req = next;
}
}
assert(BTPDQ_EMPTY(&p->my_reqs));

pc = BTPDQ_FIRST(&tmp);
while (pc != NULL) {
struct piece *next = BTPDQ_NEXT(pc, entry);
dl_piece_insert_eg(pc);
pc = next;
struct piece *next = BTPDQ_NEXT(pc, entry);
dl_piece_insert_eg(pc);
pc = next;
}
}

+ 73
- 73
btpd/main.c 파일 보기

@@ -28,15 +28,15 @@ find_homedir(void)
{
char *res = getenv("BTPD_HOME");
if (res == NULL) {
char *home = getenv("HOME");
if (home == NULL) {
struct passwd *pwent = getpwuid(getuid());
if (pwent == NULL)
errx(1, "Can't find my home directory.\n");
home = pwent->pw_dir;
endpwent();
}
asprintf(&res, "%s/.btpd", home);
char *home = getenv("HOME");
if (home == NULL) {
struct passwd *pwent = getpwuid(getuid());
if (pwent == NULL)
errx(1, "Can't find my home directory.\n");
home = pwent->pw_dir;
endpwent();
}
asprintf(&res, "%s/.btpd", home);
}
return res;
}
@@ -47,7 +47,7 @@ setup_daemon(const char *dir)
int pidfd;

if (dir == NULL)
dir = find_homedir();
dir = find_homedir();

btpd_dir = dir;

@@ -79,49 +79,49 @@ static void
usage(void)
{
printf("Usage: btpd [options]\n"
"\n"
"Options:\n"
"\n"
"--bw-hz n\n"
"\tRun the bandwidth limiter at n hz.\n"
"\tDefault is 8 hz.\n"
"\n"
"--bw-in n\n"
"\tLimit incoming BitTorrent traffic to n kB/s.\n"
"\tDefault is 0 which means unlimited.\n"
"\n"
"--bw-out n\n"
"\tLimit outgoing BitTorrent traffic to n kB/s.\n"
"\tDefault is 0 which means unlimited.\n"
"\n"
"-d\n"
"\tKeep the btpd process in the foregorund and log to std{out,err}.\n"
"\tThis option is intended for debugging purposes.\n"
"\n"
"--ipc key\n"
"\tThe same key must be used by the cli to talk to this\n"
"\tbtpd instance. You shouldn't need to use this option.\n"
"\n"
"--logfile file\n"
"\tLog to the given file. By default btpd logs to ./btpd.log.\n"
"\n"
"-p n, --port n\n"
"\tListen at port n. Default is 6881.\n"
"\n"
"--help\n"
"\tShow this help.\n"
"\n");
"\n"
"Options:\n"
"\n"
"--bw-hz n\n"
"\tRun the bandwidth limiter at n hz.\n"
"\tDefault is 8 hz.\n"
"\n"
"--bw-in n\n"
"\tLimit incoming BitTorrent traffic to n kB/s.\n"
"\tDefault is 0 which means unlimited.\n"
"\n"
"--bw-out n\n"
"\tLimit outgoing BitTorrent traffic to n kB/s.\n"
"\tDefault is 0 which means unlimited.\n"
"\n"
"-d\n"
"\tKeep the btpd process in the foregorund and log to std{out,err}.\n"
"\tThis option is intended for debugging purposes.\n"
"\n"
"--ipc key\n"
"\tThe same key must be used by the cli to talk to this\n"
"\tbtpd instance. You shouldn't need to use this option.\n"
"\n"
"--logfile file\n"
"\tLog to the given file. By default btpd logs to ./btpd.log.\n"
"\n"
"-p n, --port n\n"
"\tListen at port n. Default is 6881.\n"
"\n"
"--help\n"
"\tShow this help.\n"
"\n");
exit(1);
}

static int longval = 0;

static struct option longopts[] = {
{ "port", required_argument, NULL, 'p' },
{ "bw-in", required_argument, &longval, 1 },
{ "bw-out", required_argument, &longval, 2 },
{ "help", no_argument, &longval, 5 },
{ NULL, 0, NULL, 0 }
{ "port", required_argument, NULL, 'p' },
{ "bw-in", required_argument, &longval, 1 },
{ "bw-out", required_argument, &longval, 2 },
{ "help", no_argument, &longval, 5 },
{ NULL, 0, NULL, 0 }
};

int
@@ -132,38 +132,38 @@ main(int argc, char **argv)
setlocale(LC_ALL, "");

for (;;) {
switch (getopt_long(argc, argv, "dp:", longopts, NULL)) {
case -1:
goto args_done;
case 'd':
btpd_daemon = 0;
break;
case 'p':
net_port = atoi(optarg);
break;
case 0:
switch (longval) {
case 1:
net_bw_limit_in = atoi(optarg) * 1024;
break;
case 2:
net_bw_limit_out = atoi(optarg) * 1024;
break;
default:
usage();
}
break;
case '?':
default:
usage();
}
switch (getopt_long(argc, argv, "dp:", longopts, NULL)) {
case -1:
goto args_done;
case 'd':
btpd_daemon = 0;
break;
case 'p':
net_port = atoi(optarg);
break;
case 0:
switch (longval) {
case 1:
net_bw_limit_in = atoi(optarg) * 1024;
break;
case 2:
net_bw_limit_out = atoi(optarg) * 1024;
break;
default:
usage();
}
break;
case '?':
default:
usage();
}
}
args_done:
argc -= optind;
argv += optind;

if (argc != 0)
usage();
usage();

setup_daemon(dir);



+ 242
- 242
btpd/net.c 파일 보기

@@ -55,10 +55,10 @@ net_del_torrent(struct torrent *tp)

struct peer *p = BTPDQ_FIRST(&net_unattached);
while (p != NULL) {
struct peer *next = BTPDQ_NEXT(p, p_entry);
if (p->tp == tp)
peer_kill(p);
p = next;
struct peer *next = BTPDQ_NEXT(p, p_entry);
if (p->tp == tp)
peer_kill(p);
p = next;
}
}

@@ -89,67 +89,67 @@ net_write(struct peer *p, unsigned long wmax)
niov = 0;
assert((nl = BTPDQ_FIRST(&p->outq)) != NULL);
while ((niov < IOV_MAX && nl != NULL
&& (!limited || (limited && wmax > 0)))) {
if (niov > 0) {
iov[niov].iov_base = nl->nb->buf;
iov[niov].iov_len = nl->nb->len;
} else {
iov[niov].iov_base = nl->nb->buf + p->outq_off;
iov[niov].iov_len = nl->nb->len - p->outq_off;
}
if (limited) {
if (iov[niov].iov_len > wmax)
iov[niov].iov_len = wmax;
wmax -= iov[niov].iov_len;
}
niov++;
nl = BTPDQ_NEXT(nl, entry);
&& (!limited || (limited && wmax > 0)))) {
if (niov > 0) {
iov[niov].iov_base = nl->nb->buf;
iov[niov].iov_len = nl->nb->len;
} else {
iov[niov].iov_base = nl->nb->buf + p->outq_off;
iov[niov].iov_len = nl->nb->len - p->outq_off;
}
if (limited) {
if (iov[niov].iov_len > wmax)
iov[niov].iov_len = wmax;
wmax -= iov[niov].iov_len;
}
niov++;
nl = BTPDQ_NEXT(nl, entry);
}

nwritten = writev(p->sd, iov, niov);
if (nwritten < 0) {
if (errno == EAGAIN) {
event_add(&p->out_ev, WRITE_TIMEOUT);
return 0;
} else {
btpd_log(BTPD_L_CONN, "write error: %s\n", strerror(errno));
peer_kill(p);
return 0;
}
if (errno == EAGAIN) {
event_add(&p->out_ev, WRITE_TIMEOUT);
return 0;
} else {
btpd_log(BTPD_L_CONN, "write error: %s\n", strerror(errno));
peer_kill(p);
return 0;
}
} else if (nwritten == 0) {
btpd_log(BTPD_L_CONN, "connection closed by peer.\n");
peer_kill(p);
return 0;
btpd_log(BTPD_L_CONN, "connection closed by peer.\n");
peer_kill(p);
return 0;
}

bcount = nwritten;

nl = BTPDQ_FIRST(&p->outq);
while (bcount > 0) {
unsigned long bufdelta = nl->nb->len - p->outq_off;
if (bcount >= bufdelta) {
peer_sent(p, nl->nb);
if (nl->nb->type == NB_TORRENTDATA) {
p->tp->uploaded += bufdelta;
p->count_up += bufdelta;
}
bcount -= bufdelta;
BTPDQ_REMOVE(&p->outq, nl, entry);
nb_drop(nl->nb);
free(nl);
p->outq_off = 0;
nl = BTPDQ_FIRST(&p->outq);
} else {
if (nl->nb->type == NB_TORRENTDATA) {
p->tp->uploaded += bcount;
p->count_up += bcount;
}
p->outq_off += bcount;
bcount = 0;
}
unsigned long bufdelta = nl->nb->len - p->outq_off;
if (bcount >= bufdelta) {
peer_sent(p, nl->nb);
if (nl->nb->type == NB_TORRENTDATA) {
p->tp->uploaded += bufdelta;
p->count_up += bufdelta;
}
bcount -= bufdelta;
BTPDQ_REMOVE(&p->outq, nl, entry);
nb_drop(nl->nb);
free(nl);
p->outq_off = 0;
nl = BTPDQ_FIRST(&p->outq);
} else {
if (nl->nb->type == NB_TORRENTDATA) {
p->tp->uploaded += bcount;
p->count_up += bcount;
}
p->outq_off += bcount;
bcount = 0;
}
}
if (!BTPDQ_EMPTY(&p->outq))
event_add(&p->out_ev, WRITE_TIMEOUT);
event_add(&p->out_ev, WRITE_TIMEOUT);

return nwritten;
}
@@ -169,55 +169,55 @@ net_dispatch_msg(struct peer *p, const char *buf)

switch (p->net.msg_num) {
case MSG_CHOKE:
peer_on_choke(p);
break;
peer_on_choke(p);
break;
case MSG_UNCHOKE:
peer_on_unchoke(p);
break;
peer_on_unchoke(p);
break;
case MSG_INTEREST:
peer_on_interest(p);
break;
peer_on_interest(p);
break;
case MSG_UNINTEREST:
peer_on_uninterest(p);
break;
peer_on_uninterest(p);
break;
case MSG_HAVE:
peer_on_have(p, net_read32(buf));
break;
peer_on_have(p, net_read32(buf));
break;
case MSG_BITFIELD:
if (p->npieces == 0)
peer_on_bitfield(p, buf);
else
res = 1;
break;
break;
case MSG_REQUEST:
if ((p->flags & (PF_P_WANT|PF_I_CHOKE)) == PF_P_WANT) {
index = net_read32(buf);
begin = net_read32(buf + 4);
length = net_read32(buf + 8);
if ((length > PIECE_BLOCKLEN
|| index >= p->tp->meta.npieces
|| !has_bit(p->tp->piece_field, index)
|| begin + length > torrent_piece_size(p->tp, index))) {
if ((p->flags & (PF_P_WANT|PF_I_CHOKE)) == PF_P_WANT) {
index = net_read32(buf);
begin = net_read32(buf + 4);
length = net_read32(buf + 8);
if ((length > PIECE_BLOCKLEN
|| index >= p->tp->meta.npieces
|| !has_bit(p->tp->piece_field, index)
|| begin + length > torrent_piece_size(p->tp, index))) {
btpd_log(BTPD_L_MSG, "bad request: (%u, %u, %u) from %p\n",
index, begin, length, p);
res = 1;
break;
}
peer_on_request(p, index, begin, length);
}
break;
res = 1;
break;
}
peer_on_request(p, index, begin, length);
}
break;
case MSG_CANCEL:
index = net_read32(buf);
begin = net_read32(buf + 4);
length = net_read32(buf + 8);
peer_on_cancel(p, index, begin, length);
break;
index = net_read32(buf);
begin = net_read32(buf + 4);
length = net_read32(buf + 8);
peer_on_cancel(p, index, begin, length);
break;
case MSG_PIECE:
length = p->net.msg_len - 9;
peer_on_piece(p, p->net.pc_index, p->net.pc_begin, length, buf);
break;
length = p->net.msg_len - 9;
peer_on_piece(p, p->net.pc_index, p->net.pc_begin, length, buf);
break;
default:
abort();
abort();
}
return res;
}
@@ -231,18 +231,18 @@ net_mh_ok(struct peer *p)
case MSG_UNCHOKE:
case MSG_INTEREST:
case MSG_UNINTEREST:
return mlen == 1;
return mlen == 1;
case MSG_HAVE:
return mlen == 5;
return mlen == 5;
case MSG_BITFIELD:
return mlen == (uint32_t)ceil(p->tp->meta.npieces / 8.0) + 1;
return mlen == (uint32_t)ceil(p->tp->meta.npieces / 8.0) + 1;
case MSG_REQUEST:
case MSG_CANCEL:
return mlen == 13;
return mlen == 13;
case MSG_PIECE:
return mlen <= PIECE_BLOCKLEN + 9;
return mlen <= PIECE_BLOCKLEN + 9;
default:
return 0;
return 0;
}
}

@@ -250,8 +250,8 @@ static void
net_progress(struct peer *p, size_t length)
{
if (p->net.state == BTP_MSGBODY && p->net.msg_num == MSG_PIECE) {
p->tp->downloaded += length;
p->count_dwn += length;
p->tp->downloaded += length;
p->count_dwn += length;
}
}

@@ -261,63 +261,63 @@ net_state(struct peer *p, const char *buf)
switch (p->net.state) {
case SHAKE_PSTR:
if (bcmp(buf, "\x13""BitTorrent protocol", 20) != 0)
goto bad;
net_set_state(p, SHAKE_INFO, 20);
goto bad;
net_set_state(p, SHAKE_INFO, 20);
break;
case SHAKE_INFO:
if (p->flags & PF_INCOMING) {
struct torrent *tp;
if (p->flags & PF_INCOMING) {
struct torrent *tp;
BTPDQ_FOREACH(tp, &m_torrents, net_entry)
if (bcmp(buf, tp->meta.info_hash, 20) == 0)
break;
if (tp == NULL)
goto bad;
p->tp = tp;
peer_send(p, nb_create_shake(p->tp));
} else if (bcmp(buf, p->tp->meta.info_hash, 20) != 0)
goto bad;
net_set_state(p, SHAKE_ID, 20);
if (tp == NULL)
goto bad;
p->tp = tp;
peer_send(p, nb_create_shake(p->tp));
} else if (bcmp(buf, p->tp->meta.info_hash, 20) != 0)
goto bad;
net_set_state(p, SHAKE_ID, 20);
break;
case SHAKE_ID:
if ((torrent_has_peer(p->tp, buf)
if ((torrent_has_peer(p->tp, buf)
|| bcmp(buf, btpd_get_peer_id(), 20) == 0))
goto bad;
bcopy(buf, p->id, 20);
goto bad;
bcopy(buf, p->id, 20);
peer_on_shake(p);
net_set_state(p, BTP_MSGSIZE, 4);
net_set_state(p, BTP_MSGSIZE, 4);
break;
case BTP_MSGSIZE:
p->net.msg_len = net_read32(buf);
if (p->net.msg_len == 0)
peer_on_keepalive(p);
else
net_set_state(p, BTP_MSGHEAD, 1);
p->net.msg_len = net_read32(buf);
if (p->net.msg_len == 0)
peer_on_keepalive(p);
else
net_set_state(p, BTP_MSGHEAD, 1);
break;
case BTP_MSGHEAD:
p->net.msg_num = buf[0];
if (!net_mh_ok(p))
goto bad;
else if (p->net.msg_len == 1) {
if (net_dispatch_msg(p, buf) != 0)
goto bad;
net_set_state(p, BTP_MSGSIZE, 4);
} else if (p->net.msg_num == MSG_PIECE)
net_set_state(p, BTP_PIECEMETA, 8);
else
net_set_state(p, BTP_MSGBODY, p->net.msg_len - 1);
p->net.msg_num = buf[0];
if (!net_mh_ok(p))
goto bad;
else if (p->net.msg_len == 1) {
if (net_dispatch_msg(p, buf) != 0)
goto bad;
net_set_state(p, BTP_MSGSIZE, 4);
} else if (p->net.msg_num == MSG_PIECE)
net_set_state(p, BTP_PIECEMETA, 8);
else
net_set_state(p, BTP_MSGBODY, p->net.msg_len - 1);
break;
case BTP_PIECEMETA:
p->net.pc_index = net_read32(buf);
p->net.pc_begin = net_read32(buf + 4);
net_set_state(p, BTP_MSGBODY, p->net.msg_len - 9);
break;
p->net.pc_index = net_read32(buf);
p->net.pc_begin = net_read32(buf + 4);
net_set_state(p, BTP_MSGBODY, p->net.msg_len - 9);
break;
case BTP_MSGBODY:
if (net_dispatch_msg(p, buf) != 0)
goto bad;
net_set_state(p, BTP_MSGSIZE, 4);
if (net_dispatch_msg(p, buf) != 0)
goto bad;
net_set_state(p, BTP_MSGSIZE, 4);
break;
default:
abort();
abort();
}

return 0;
@@ -336,44 +336,44 @@ net_read(struct peer *p, unsigned long rmax)
size_t rest = p->net.buf != NULL ? p->net.st_bytes - p->net.off : 0;
char buf[GRBUFLEN];
struct iovec iov[2] = {
{
p->net.buf + p->net.off,
rest
}, {
buf,
sizeof(buf)
}
{
p->net.buf + p->net.off,
rest
}, {
buf,
sizeof(buf)
}
};

if (rmax > 0) {
if (iov[0].iov_len > rmax)
iov[0].iov_len = rmax;
iov[1].iov_len = min(rmax - iov[0].iov_len, iov[1].iov_len);
if (iov[0].iov_len > rmax)
iov[0].iov_len = rmax;
iov[1].iov_len = min(rmax - iov[0].iov_len, iov[1].iov_len);
}

ssize_t nread = readv(p->sd, iov, 2);
if (nread < 0 && errno == EAGAIN)
goto out;
goto out;
else if (nread < 0) {
btpd_log(BTPD_L_CONN, "Read error (%s) on %p.\n", strerror(errno), p);
peer_kill(p);
return 0;
btpd_log(BTPD_L_CONN, "Read error (%s) on %p.\n", strerror(errno), p);
peer_kill(p);
return 0;
} else if (nread == 0) {
btpd_log(BTPD_L_CONN, "Connection closed by %p.\n", p);
peer_kill(p);
return 0;
btpd_log(BTPD_L_CONN, "Connection closed by %p.\n", p);
peer_kill(p);
return 0;
}

if (rest > 0) {
if (nread < rest) {
p->net.off += nread;
net_progress(p, nread);
goto out;
}
net_progress(p, rest);
if (net_state(p, p->net.buf) != 0)
return nread;
free(p->net.buf);
if (nread < rest) {
p->net.off += nread;
net_progress(p, nread);
goto out;
}
net_progress(p, rest);
if (net_state(p, p->net.buf) != 0)
return nread;
free(p->net.buf);
p->net.buf = NULL;
p->net.off = 0;
}
@@ -381,18 +381,18 @@ net_read(struct peer *p, unsigned long rmax)
iov[1].iov_len = nread - rest;
while (p->net.st_bytes <= iov[1].iov_len) {
size_t consumed = p->net.st_bytes;
net_progress(p, consumed);
if (net_state(p, iov[1].iov_base) != 0)
return nread;
iov[1].iov_base += consumed;
iov[1].iov_len -= consumed;
net_progress(p, consumed);
if (net_state(p, iov[1].iov_base) != 0)
return nread;
iov[1].iov_base += consumed;
iov[1].iov_len -= consumed;
}

if (iov[1].iov_len > 0) {
net_progress(p, iov[1].iov_len);
p->net.off = iov[1].iov_len;
p->net.buf = btpd_malloc(p->net.st_bytes);
bcopy(iov[1].iov_base, p->net.buf, iov[1].iov_len);
net_progress(p, iov[1].iov_len);
p->net.off = iov[1].iov_len;
p->net.buf = btpd_malloc(p->net.st_bytes);
bcopy(iov[1].iov_base, p->net.buf, iov[1].iov_len);
}

out:
@@ -403,15 +403,15 @@ out:
int
net_connect2(struct sockaddr *sa, socklen_t salen, int *sd)
{
if ((*sd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
return errno;
if ((*sd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
return errno;
set_nonblocking(*sd);

if (connect(*sd, sa, salen) == -1 && errno != EINPROGRESS) {
btpd_log(BTPD_L_CONN, "Botched connection %s.", strerror(errno));
close(*sd);
return errno;
btpd_log(BTPD_L_CONN, "Botched connection %s.", strerror(errno));
close(*sd);
return errno;
}

return 0;
@@ -422,17 +422,17 @@ net_connect(const char *ip, int port, int *sd)
{
struct addrinfo hints, *res;
char portstr[6];
assert(net_npeers < net_max_peers);

if (snprintf(portstr, sizeof(portstr), "%d", port) >= sizeof(portstr))
return EINVAL;
return EINVAL;
bzero(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_flags = AI_NUMERICHOST;
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo(ip, portstr, &hints, &res) != 0)
return errno;
return errno;

int error = net_connect2(res->ai_addr, res->ai_addrlen, sd);
freeaddrinfo(res);
@@ -446,21 +446,21 @@ net_connection_cb(int sd, short type, void *arg)

nsd = accept(sd, NULL, NULL);
if (nsd < 0) {
if (errno == EWOULDBLOCK || errno == ECONNABORTED)
return;
else
btpd_err("accept4: %s\n", strerror(errno));
if (errno == EWOULDBLOCK || errno == ECONNABORTED)
return;
else
btpd_err("accept4: %s\n", strerror(errno));
}

if (set_nonblocking(nsd) != 0) {
close(nsd);
return;
close(nsd);
return;
}

assert(net_npeers <= net_max_peers);
if (net_npeers == net_max_peers) {
close(nsd);
return;
close(nsd);
return;
}

peer_create_in(nsd);
@@ -474,35 +474,35 @@ long
compute_rate_sub(long rate)
{
if (rate > 256 * RATEHISTORY)
return rate / RATEHISTORY;
return rate / RATEHISTORY;
else
return 256;
return 256;
}

static void
compute_peer_rates(void) {
struct torrent *tp;
BTPDQ_FOREACH(tp, &m_torrents, net_entry) {
struct peer *p;
BTPDQ_FOREACH(p, &tp->peers, p_entry) {
if (p->count_up > 0 || peer_active_up(p)) {
p->rate_up += p->count_up - compute_rate_sub(p->rate_up);
if (p->rate_up < 0)
p->rate_up = 0;
p->count_up = 0;
}
if (p->count_dwn > 0 || peer_active_down(p)) {
p->rate_dwn += p->count_dwn - compute_rate_sub(p->rate_dwn);
if (p->rate_dwn < 0)
p->rate_dwn = 0;
p->count_dwn = 0;
}
}
struct peer *p;
BTPDQ_FOREACH(p, &tp->peers, p_entry) {
if (p->count_up > 0 || peer_active_up(p)) {
p->rate_up += p->count_up - compute_rate_sub(p->rate_up);
if (p->rate_up < 0)
p->rate_up = 0;
p->count_up = 0;
}
if (p->count_dwn > 0 || peer_active_down(p)) {
p->rate_dwn += p->count_dwn - compute_rate_sub(p->rate_dwn);
if (p->rate_dwn < 0)
p->rate_dwn = 0;
p->count_dwn = 0;
}
}
}
}

void
net_bw_cb(int sd, short type, void *arg)
net_bw_cb(int sd, short type, void *arg)
{
struct peer *p;

@@ -514,31 +514,31 @@ net_bw_cb(int sd, short type, void *arg)
m_bw_bytes_in = net_bw_limit_in;

if (net_bw_limit_in > 0) {
while ((p = BTPDQ_FIRST(&net_bw_readq)) != NULL && m_bw_bytes_in > 0) {
BTPDQ_REMOVE(&net_bw_readq, p, rq_entry);
p->flags &= ~PF_ON_READQ;
m_bw_bytes_in -= net_read(p, m_bw_bytes_in);
}
while ((p = BTPDQ_FIRST(&net_bw_readq)) != NULL && m_bw_bytes_in > 0) {
BTPDQ_REMOVE(&net_bw_readq, p, rq_entry);
p->flags &= ~PF_ON_READQ;
m_bw_bytes_in -= net_read(p, m_bw_bytes_in);
}
} else {
while ((p = BTPDQ_FIRST(&net_bw_readq)) != NULL) {
BTPDQ_REMOVE(&net_bw_readq, p, rq_entry);
p->flags &= ~PF_ON_READQ;
net_read(p, 0);
}
while ((p = BTPDQ_FIRST(&net_bw_readq)) != NULL) {
BTPDQ_REMOVE(&net_bw_readq, p, rq_entry);
p->flags &= ~PF_ON_READQ;
net_read(p, 0);
}
}

if (net_bw_limit_out) {
while ((p = BTPDQ_FIRST(&net_bw_writeq)) != NULL && m_bw_bytes_out > 0) {
BTPDQ_REMOVE(&net_bw_writeq, p, wq_entry);
p->flags &= ~PF_ON_WRITEQ;
m_bw_bytes_out -= net_write(p, m_bw_bytes_out);
}
while ((p = BTPDQ_FIRST(&net_bw_writeq)) != NULL && m_bw_bytes_out > 0) {
BTPDQ_REMOVE(&net_bw_writeq, p, wq_entry);
p->flags &= ~PF_ON_WRITEQ;
m_bw_bytes_out -= net_write(p, m_bw_bytes_out);
}
} else {
while ((p = BTPDQ_FIRST(&net_bw_writeq)) != NULL) {
BTPDQ_REMOVE(&net_bw_writeq, p, wq_entry);
p->flags &= ~PF_ON_WRITEQ;
net_write(p, 0);
}
while ((p = BTPDQ_FIRST(&net_bw_writeq)) != NULL) {
BTPDQ_REMOVE(&net_bw_writeq, p, wq_entry);
p->flags &= ~PF_ON_WRITEQ;
net_write(p, 0);
}
}
}

@@ -547,12 +547,12 @@ net_read_cb(int sd, short type, void *arg)
{
struct peer *p = (struct peer *)arg;
if (net_bw_limit_in == 0)
net_read(p, 0);
net_read(p, 0);
else if (m_bw_bytes_in > 0)
m_bw_bytes_in -= net_read(p, m_bw_bytes_in);
m_bw_bytes_in -= net_read(p, m_bw_bytes_in);
else {
p->flags |= PF_ON_READQ;
BTPDQ_INSERT_TAIL(&net_bw_readq, p, rq_entry);
p->flags |= PF_ON_READQ;
BTPDQ_INSERT_TAIL(&net_bw_readq, p, rq_entry);
}
}

@@ -561,17 +561,17 @@ net_write_cb(int sd, short type, void *arg)
{
struct peer *p = (struct peer *)arg;
if (type == EV_TIMEOUT) {
btpd_log(BTPD_L_CONN, "Write attempt timed out.\n");
peer_kill(p);
return;
btpd_log(BTPD_L_CONN, "Write attempt timed out.\n");
peer_kill(p);
return;
}
if (net_bw_limit_out == 0) {
net_write(p, 0);
net_write(p, 0);
} else if (m_bw_bytes_out > 0) {
m_bw_bytes_out -= net_write(p, m_bw_bytes_out);
m_bw_bytes_out -= net_write(p, m_bw_bytes_out);
} else {
p->flags |= PF_ON_WRITEQ;
BTPDQ_INSERT_TAIL(&net_bw_writeq, p, wq_entry);
p->flags |= PF_ON_WRITEQ;
BTPDQ_INSERT_TAIL(&net_bw_writeq, p, wq_entry);
}
}

@@ -583,13 +583,13 @@ net_init(void)

int nfiles = getdtablesize();
if (nfiles <= 20)
btpd_err("Too few open files allowed (%d). "
"Check \"ulimit -n\"\n", nfiles);
btpd_err("Too few open files allowed (%d). "
"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);
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;
@@ -600,10 +600,10 @@ net_init(void)
addr.sin_port = htons(net_port);

if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
btpd_err("socket: %s\n", strerror(errno));
btpd_err("socket: %s\n", strerror(errno));
setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));
if (bind(sd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
btpd_err("bind: %s\n", strerror(errno));
btpd_err("bind: %s\n", strerror(errno));
listen(sd, 10);
set_nonblocking(sd);



+ 9
- 9
btpd/net.h 파일 보기

@@ -1,15 +1,15 @@
#ifndef BTPD_NET_H
#define BTPD_NET_H

#define MSG_CHOKE 0
#define MSG_UNCHOKE 1
#define MSG_INTEREST 2
#define MSG_UNINTEREST 3
#define MSG_HAVE 4
#define MSG_BITFIELD 5
#define MSG_REQUEST 6
#define MSG_PIECE 7
#define MSG_CANCEL 8
#define MSG_CHOKE 0
#define MSG_UNCHOKE 1
#define MSG_INTEREST 2
#define MSG_UNINTEREST 3
#define MSG_HAVE 4
#define MSG_BITFIELD 5
#define MSG_REQUEST 6
#define MSG_PIECE 7
#define MSG_CANCEL 8

#define WRITE_TIMEOUT (& (struct timeval) { 60, 0 })



+ 24
- 24
btpd/net_buf.c 파일 보기

@@ -123,12 +123,12 @@ nb_create_multihave(struct torrent *tp)
{
struct net_buf *out = nb_create_alloc(NB_MULTIHAVE, 9 * tp->have_npieces);
for (uint32_t i = 0, count = 0; count < tp->have_npieces; i++) {
if (has_bit(tp->piece_field, i)) {
net_write32(out->buf + count * 9, 5);
out->buf[count * 9 + 4] = MSG_HAVE;
net_write32(out->buf + count * 9 + 5, i);
count++;
}
if (has_bit(tp->piece_field, i)) {
net_write32(out->buf + count * 9, 5);
out->buf[count * 9 + 4] = MSG_HAVE;
net_write32(out->buf + count * 9 + 5, i);
count++;
}
}
return out;
}
@@ -137,7 +137,7 @@ struct net_buf *
nb_create_unchoke(void)
{
if (m_unchoke == NULL)
m_unchoke = nb_singleton(nb_create_onesized(MSG_UNCHOKE, NB_UNCHOKE));
m_unchoke = nb_singleton(nb_create_onesized(MSG_UNCHOKE, NB_UNCHOKE));
return m_unchoke;
}

@@ -145,7 +145,7 @@ struct net_buf *
nb_create_choke(void)
{
if (m_choke == NULL)
m_choke = nb_singleton(nb_create_onesized(MSG_CHOKE, NB_CHOKE));
m_choke = nb_singleton(nb_create_onesized(MSG_CHOKE, NB_CHOKE));
return m_choke;
}

@@ -153,8 +153,8 @@ struct net_buf *
nb_create_uninterest(void)
{
if (m_uninterest == NULL)
m_uninterest =
nb_singleton(nb_create_onesized(MSG_UNINTEREST, NB_UNINTEREST));
m_uninterest =
nb_singleton(nb_create_onesized(MSG_UNINTEREST, NB_UNINTEREST));
return m_uninterest;
}

@@ -162,8 +162,8 @@ struct net_buf *
nb_create_interest(void)
{
if (m_interest == NULL)
m_interest =
nb_singleton(nb_create_onesized(MSG_INTEREST, NB_INTEREST));
m_interest =
nb_singleton(nb_create_onesized(MSG_INTEREST, NB_INTEREST));
return m_interest;
}

@@ -183,7 +183,7 @@ nb_create_bitdata(struct torrent *tp)
{
uint32_t plen = ceil(tp->meta.npieces / 8.0);
struct net_buf *out =
nb_create_set(NB_BITDATA, tp->piece_field, plen, kill_buf_no);
nb_create_set(NB_BITDATA, tp->piece_field, plen, kill_buf_no);
return out;
}

@@ -205,9 +205,9 @@ nb_get_index(struct net_buf *nb)
case NB_HAVE:
case NB_PIECE:
case NB_REQUEST:
return net_read32(nb->buf + 5);
return net_read32(nb->buf + 5);
default:
abort();
abort();
}
}

@@ -218,9 +218,9 @@ nb_get_begin(struct net_buf *nb)
case NB_CANCEL:
case NB_PIECE:
case NB_REQUEST:
return net_read32(nb->buf + 9);
return net_read32(nb->buf + 9);
default:
abort();
abort();
}
}

@@ -230,11 +230,11 @@ nb_get_length(struct net_buf *nb)
switch (nb->type) {
case NB_CANCEL:
case NB_REQUEST:
return net_read32(nb->buf + 13);
return net_read32(nb->buf + 13);
case NB_PIECE:
return net_read32(nb->buf) - 9;
return net_read32(nb->buf) - 9;
default:
abort();
abort();
}
}

@@ -244,11 +244,11 @@ nb_drop(struct net_buf *nb)
assert(nb->refs > 0);
nb->refs--;
if (nb->refs == 0) {
nb->kill_buf(nb->buf, nb->len);
free(nb);
return 1;
nb->kill_buf(nb->buf, nb->len);
free(nb);
return 1;
} else
return 0;
return 0;
}

void


+ 13
- 13
btpd/net_buf.h 파일 보기

@@ -1,19 +1,19 @@
#ifndef BTPD_NET_BUF_H
#define BTPD_NET_BUF_H

#define NB_CHOKE 0
#define NB_UNCHOKE 1
#define NB_INTEREST 2
#define NB_UNINTEREST 3
#define NB_HAVE 4
#define NB_BITFIELD 5
#define NB_REQUEST 6
#define NB_PIECE 7
#define NB_CANCEL 8
#define NB_TORRENTDATA 10
#define NB_MULTIHAVE 11
#define NB_BITDATA 12
#define NB_SHAKE 13
#define NB_CHOKE 0
#define NB_UNCHOKE 1
#define NB_INTEREST 2
#define NB_UNINTEREST 3
#define NB_HAVE 4
#define NB_BITFIELD 5
#define NB_REQUEST 6
#define NB_PIECE 7
#define NB_CANCEL 8
#define NB_TORRENTDATA 10
#define NB_MULTIHAVE 11
#define NB_BITDATA 12
#define NB_SHAKE 13

struct net_buf {
short type;


+ 164
- 164
btpd/peer.c 파일 보기

@@ -18,13 +18,13 @@ peer_kill(struct peer *p)

if (p->flags & PF_ATTACHED) {
ul_on_lost_peer(p);
dl_on_lost_peer(p);
dl_on_lost_peer(p);
} else
BTPDQ_REMOVE(&net_unattached, p, p_entry);
BTPDQ_REMOVE(&net_unattached, p, p_entry);
if (p->flags & PF_ON_READQ)
BTPDQ_REMOVE(&net_bw_readq, p, rq_entry);
BTPDQ_REMOVE(&net_bw_readq, p, rq_entry);
if (p->flags & PF_ON_WRITEQ)
BTPDQ_REMOVE(&net_bw_writeq, p, wq_entry);
BTPDQ_REMOVE(&net_bw_writeq, p, wq_entry);

close(p->sd);
event_del(&p->in_ev);
@@ -32,14 +32,14 @@ peer_kill(struct peer *p)

nl = BTPDQ_FIRST(&p->outq);
while (nl != NULL) {
struct nb_link *next = BTPDQ_NEXT(nl, entry);
nb_drop(nl->nb);
free(nl);
nl = next;
struct nb_link *next = BTPDQ_NEXT(nl, entry);
nb_drop(nl->nb);
free(nl);
nl = next;
}

if (p->net.buf != NULL)
free(p->net.buf);
free(p->net.buf);
if (p->piece_field != NULL)
free(p->piece_field);
free(p);
@@ -54,8 +54,8 @@ peer_send(struct peer *p, struct net_buf *nb)
nb_hold(nb);

if (BTPDQ_EMPTY(&p->outq)) {
assert(p->outq_off == 0);
event_add(&p->out_ev, WRITE_TIMEOUT);
assert(p->outq_off == 0);
event_add(&p->out_ev, WRITE_TIMEOUT);
}
BTPDQ_INSERT_TAIL(&p->outq, nl, entry);
}
@@ -71,23 +71,23 @@ int
peer_unsend(struct peer *p, struct nb_link *nl)
{
if (!(nl == BTPDQ_FIRST(&p->outq) && p->outq_off > 0)) {
BTPDQ_REMOVE(&p->outq, nl, entry);
if (nl->nb->type == NB_TORRENTDATA) {
assert(p->npiece_msgs > 0);
p->npiece_msgs--;
}
nb_drop(nl->nb);
free(nl);
if (BTPDQ_EMPTY(&p->outq)) {
if (p->flags & PF_ON_WRITEQ) {
BTPDQ_REMOVE(&net_bw_writeq, p, wq_entry);
p->flags &= ~PF_ON_WRITEQ;
} else
event_del(&p->out_ev);
}
return 1;
BTPDQ_REMOVE(&p->outq, nl, entry);
if (nl->nb->type == NB_TORRENTDATA) {
assert(p->npiece_msgs > 0);
p->npiece_msgs--;
}
nb_drop(nl->nb);
free(nl);
if (BTPDQ_EMPTY(&p->outq)) {
if (p->flags & PF_ON_WRITEQ) {
BTPDQ_REMOVE(&net_bw_writeq, p, wq_entry);
p->flags &= ~PF_ON_WRITEQ;
} else
event_del(&p->out_ev);
}
return 1;
} else
return 0;
return 0;
}

void
@@ -95,51 +95,51 @@ peer_sent(struct peer *p, struct net_buf *nb)
{
switch (nb->type) {
case NB_CHOKE:
btpd_log(BTPD_L_MSG, "sent choke to %p\n", p);
break;
btpd_log(BTPD_L_MSG, "sent choke to %p\n", p);
break;
case NB_UNCHOKE:
btpd_log(BTPD_L_MSG, "sent unchoke to %p\n", p);
p->flags &= ~PF_NO_REQUESTS;
break;
btpd_log(BTPD_L_MSG, "sent unchoke to %p\n", p);
p->flags &= ~PF_NO_REQUESTS;
break;
case NB_INTEREST:
btpd_log(BTPD_L_MSG, "sent interest to %p\n", p);
break;
btpd_log(BTPD_L_MSG, "sent interest to %p\n", p);
break;
case NB_UNINTEREST:
btpd_log(BTPD_L_MSG, "sent uninterest to %p\n", p);
break;
btpd_log(BTPD_L_MSG, "sent uninterest to %p\n", p);
break;
case NB_HAVE:
btpd_log(BTPD_L_MSG, "sent have(%u) to %p\n",
nb_get_index(nb), p);
break;
btpd_log(BTPD_L_MSG, "sent have(%u) to %p\n",
nb_get_index(nb), p);
break;
case NB_BITFIELD:
btpd_log(BTPD_L_MSG, "sent bitfield to %p\n", p);
break;
btpd_log(BTPD_L_MSG, "sent bitfield to %p\n", p);
break;
case NB_REQUEST:
btpd_log(BTPD_L_MSG, "sent request(%u,%u,%u) to %p\n",
nb_get_index(nb), nb_get_begin(nb), nb_get_length(nb), p);
break;
btpd_log(BTPD_L_MSG, "sent request(%u,%u,%u) to %p\n",
nb_get_index(nb), nb_get_begin(nb), nb_get_length(nb), p);
break;
case NB_PIECE:
btpd_log(BTPD_L_MSG, "sent piece(%u,%u,%u) to %p\n",
nb_get_index(nb), nb_get_begin(nb), nb_get_length(nb), p);
break;
btpd_log(BTPD_L_MSG, "sent piece(%u,%u,%u) to %p\n",
nb_get_index(nb), nb_get_begin(nb), nb_get_length(nb), p);
break;
case NB_CANCEL:
btpd_log(BTPD_L_MSG, "sent cancel(%u,%u,%u) to %p\n",
nb_get_index(nb), nb_get_begin(nb), nb_get_length(nb), p);
break;
btpd_log(BTPD_L_MSG, "sent cancel(%u,%u,%u) to %p\n",
nb_get_index(nb), nb_get_begin(nb), nb_get_length(nb), p);
break;
case NB_TORRENTDATA:
btpd_log(BTPD_L_MSG, "sent data to %p\n", p);
assert(p->npiece_msgs > 0);
p->npiece_msgs--;
break;
btpd_log(BTPD_L_MSG, "sent data to %p\n", p);
assert(p->npiece_msgs > 0);
p->npiece_msgs--;
break;
case NB_MULTIHAVE:
btpd_log(BTPD_L_MSG, "sent multihave to %p\n", p);
break;
btpd_log(BTPD_L_MSG, "sent multihave to %p\n", p);
break;
case NB_BITDATA:
btpd_log(BTPD_L_MSG, "sent bitdata to %p\n", p);
break;
btpd_log(BTPD_L_MSG, "sent bitdata to %p\n", p);
break;
case NB_SHAKE:
btpd_log(BTPD_L_MSG, "sent shake to %p\n", p);
break;
btpd_log(BTPD_L_MSG, "sent shake to %p\n", p);
break;
}
}

@@ -157,8 +157,8 @@ peer_requested(struct peer *p, struct block *blk)
{
struct block_request *req;
BTPDQ_FOREACH(req, &p->my_reqs, p_entry)
if (req->blk == blk)
return 1;
if (req->blk == blk)
return 1;
return 0;
}

@@ -171,15 +171,15 @@ peer_cancel(struct peer *p, struct block_request *req, struct net_buf *nb)
int removed = 0;
struct nb_link *nl;
BTPDQ_FOREACH(nl, &p->outq, entry) {
if (nl->nb == req->blk->msg) {
removed = peer_unsend(p, nl);
break;
}
if (nl->nb == req->blk->msg) {
removed = peer_unsend(p, nl);
break;
}
}
if (!removed)
peer_send(p, nb);
peer_send(p, nb);
if (p->nreqs_out == 0)
peer_on_no_reqs(p);
peer_on_no_reqs(p);
}

void
@@ -194,14 +194,14 @@ peer_choke(struct peer *p)
{
struct nb_link *nl = BTPDQ_FIRST(&p->outq);
while (nl != NULL) {
struct nb_link *next = BTPDQ_NEXT(nl, entry);
if (nl->nb->type == NB_PIECE) {
struct nb_link *data = next;
next = BTPDQ_NEXT(next, entry);
if (peer_unsend(p, nl))
peer_unsend(p, data);
}
nl = next;
struct nb_link *next = BTPDQ_NEXT(nl, entry);
if (nl->nb->type == NB_PIECE) {
struct nb_link *data = next;
next = BTPDQ_NEXT(next, entry);
if (peer_unsend(p, nl))
peer_unsend(p, data);
}
nl = next;
}

p->flags |= PF_I_CHOKE;
@@ -214,19 +214,19 @@ peer_want(struct peer *p, uint32_t index)
assert(p->nwant < p->npieces);
p->nwant++;
if (p->nwant == 1) {
if (p->nreqs_out == 0) {
assert((p->flags & PF_DO_UNWANT) == 0);
int unsent = 0;
struct nb_link *nl = BTPDQ_LAST(&p->outq, nb_tq);
if (nl != NULL && nl->nb->type == NB_UNINTEREST)
unsent = peer_unsend(p, nl);
if (!unsent)
peer_send(p, nb_create_interest());
} else {
assert((p->flags & PF_DO_UNWANT) != 0);
p->flags &= ~PF_DO_UNWANT;
}
p->flags |= PF_I_WANT;
if (p->nreqs_out == 0) {
assert((p->flags & PF_DO_UNWANT) == 0);
int unsent = 0;
struct nb_link *nl = BTPDQ_LAST(&p->outq, nb_tq);
if (nl != NULL && nl->nb->type == NB_UNINTEREST)
unsent = peer_unsend(p, nl);
if (!unsent)
peer_send(p, nb_create_interest());
} else {
assert((p->flags & PF_DO_UNWANT) != 0);
p->flags &= ~PF_DO_UNWANT;
}
p->flags |= PF_I_WANT;
}
}

@@ -236,11 +236,11 @@ peer_unwant(struct peer *p, uint32_t index)
assert(p->nwant > 0);
p->nwant--;
if (p->nwant == 0) {
p->flags &= ~PF_I_WANT;
if (p->nreqs_out == 0)
peer_send(p, nb_create_uninterest());
else
p->flags |= PF_DO_UNWANT;
p->flags &= ~PF_I_WANT;
if (p->nreqs_out == 0)
peer_send(p, nb_create_uninterest());
else
p->flags |= PF_DO_UNWANT;
}
}

@@ -280,7 +280,7 @@ peer_create_out(struct torrent *tp, const uint8_t *id,
struct peer *p;

if (net_connect(ip, port, &sd) != 0)
return;
return;

p = peer_create_common(sd);
p->tp = tp;
@@ -299,7 +299,7 @@ peer_create_out_compact(struct torrent *tp, const char *compact)
addr.sin_port = *(short *)(compact + 4);

if (net_connect2((struct sockaddr *)&addr, sizeof(addr), &sd) != 0)
return;
return;

p = peer_create_common(sd);
p->tp = tp;
@@ -310,9 +310,9 @@ void
peer_on_no_reqs(struct peer *p)
{
if ((p->flags & PF_DO_UNWANT) != 0) {
assert(p->nwant == 0);
p->flags &= ~PF_DO_UNWANT;
peer_send(p, nb_create_uninterest());
assert(p->nwant == 0);
p->flags &= ~PF_DO_UNWANT;
peer_send(p, nb_create_uninterest());
}
}

@@ -328,7 +328,7 @@ peer_on_shake(struct peer *p)
uint8_t printid[21];
int i;
for (i = 0; i < 20 && isprint(p->id[i]); i++)
printid[i] = p->id[i];
printid[i] = p->id[i];
printid[i] = '\0';
btpd_log(BTPD_L_MSG, "received shake(%s) from %p\n", printid, p);
p->piece_field = btpd_calloc(1, (int)ceil(p->tp->meta.npieces / 8.0));
@@ -349,19 +349,19 @@ peer_on_choke(struct peer *p)
{
btpd_log(BTPD_L_MSG, "received choke from %p\n", p);
if ((p->flags & PF_P_CHOKE) != 0)
return;
return;
else {
if (p->nreqs_out > 0)
peer_on_no_reqs(p);
p->flags |= PF_P_CHOKE;
dl_on_choke(p);
struct nb_link *nl = BTPDQ_FIRST(&p->outq);
while (nl != NULL) {
struct nb_link *next = BTPDQ_NEXT(nl, entry);
if (nl->nb->type == NB_REQUEST)
peer_unsend(p, nl);
nl = next;
}
if (p->nreqs_out > 0)
peer_on_no_reqs(p);
p->flags |= PF_P_CHOKE;
dl_on_choke(p);
struct nb_link *nl = BTPDQ_FIRST(&p->outq);
while (nl != NULL) {
struct nb_link *next = BTPDQ_NEXT(nl, entry);
if (nl->nb->type == NB_REQUEST)
peer_unsend(p, nl);
nl = next;
}
}
}

@@ -370,10 +370,10 @@ peer_on_unchoke(struct peer *p)
{
btpd_log(BTPD_L_MSG, "received unchoke from %p\n", p);
if ((p->flags & PF_P_CHOKE) == 0)
return;
return;
else {
p->flags &= ~PF_P_CHOKE;
dl_on_unchoke(p);
p->flags &= ~PF_P_CHOKE;
dl_on_unchoke(p);
}
}

@@ -382,10 +382,10 @@ peer_on_interest(struct peer *p)
{
btpd_log(BTPD_L_MSG, "received interest from %p\n", p);
if ((p->flags & PF_P_WANT) != 0)
return;
return;
else {
p->flags |= PF_P_WANT;
ul_on_interest(p);
p->flags |= PF_P_WANT;
ul_on_interest(p);
}
}

@@ -394,10 +394,10 @@ peer_on_uninterest(struct peer *p)
{
btpd_log(BTPD_L_MSG, "received uninterest from %p\n", p);
if ((p->flags & PF_P_WANT) == 0)
return;
return;
else {
p->flags &= ~PF_P_WANT;
ul_on_uninterest(p);
p->flags &= ~PF_P_WANT;
ul_on_uninterest(p);
}
}

@@ -406,9 +406,9 @@ peer_on_have(struct peer *p, uint32_t index)
{
btpd_log(BTPD_L_MSG, "received have(%u) from %p\n", index, p);
if (!has_bit(p->piece_field, index)) {
set_bit(p->piece_field, index);
p->npieces++;
dl_on_piece_ann(p, index);
set_bit(p->piece_field, index);
p->npieces++;
dl_on_piece_ann(p, index);
}
}

@@ -419,10 +419,10 @@ peer_on_bitfield(struct peer *p, const uint8_t *field)
assert(p->npieces == 0);
bcopy(field, p->piece_field, (size_t)ceil(p->tp->meta.npieces / 8.0));
for (uint32_t i = 0; i < p->tp->meta.npieces; i++) {
if (has_bit(p->piece_field, i)) {
p->npieces++;
dl_on_piece_ann(p, i);
}
if (has_bit(p->piece_field, i)) {
p->npieces++;
dl_on_piece_ann(p, i);
}
}
}

@@ -432,22 +432,22 @@ peer_on_piece(struct peer *p, uint32_t index, uint32_t begin,
{
struct block_request *req;
BTPDQ_FOREACH(req, &p->my_reqs, p_entry)
if ((nb_get_begin(req->blk->msg) == begin &&
nb_get_index(req->blk->msg) == index &&
nb_get_length(req->blk->msg) == length))
break;
if ((nb_get_begin(req->blk->msg) == begin &&
nb_get_index(req->blk->msg) == index &&
nb_get_length(req->blk->msg) == length))
break;
if (req != NULL) {
btpd_log(BTPD_L_MSG, "received piece(%u,%u,%u) from %p\n",
index, begin, length, p);
assert(p->nreqs_out > 0);
p->nreqs_out--;
BTPDQ_REMOVE(&p->my_reqs, req, p_entry);
dl_on_block(p, req, index, begin, length, data);
if (p->nreqs_out == 0)
peer_on_no_reqs(p);
btpd_log(BTPD_L_MSG, "received piece(%u,%u,%u) from %p\n",
index, begin, length, p);
assert(p->nreqs_out > 0);
p->nreqs_out--;
BTPDQ_REMOVE(&p->my_reqs, req, p_entry);
dl_on_block(p, req, index, begin, length, data);
if (p->nreqs_out == 0)
peer_on_no_reqs(p);
} else
btpd_log(BTPD_L_MSG, "discarded piece(%u,%u,%u) from %p\n",
index, begin, length, p);
btpd_log(BTPD_L_MSG, "discarded piece(%u,%u,%u) from %p\n",
index, begin, length, p);
}

void
@@ -455,18 +455,18 @@ peer_on_request(struct peer *p, uint32_t index, uint32_t begin,
uint32_t length)
{
btpd_log(BTPD_L_MSG, "received request(%u,%u,%u) from %p\n",
index, begin, length, p);
index, begin, length, p);
if ((p->flags & PF_NO_REQUESTS) == 0) {
off_t cbegin = index * p->tp->meta.piece_length + begin;
char * content = torrent_get_bytes(p->tp, cbegin, length);
peer_send(p, nb_create_piece(index, begin, length));
peer_send(p, nb_create_torrentdata(content, length));
p->npiece_msgs++;
if (p->npiece_msgs >= MAXPIECEMSGS) {
peer_send(p, nb_create_choke());
peer_send(p, nb_create_unchoke());
p->flags |= PF_NO_REQUESTS;
}
off_t cbegin = index * p->tp->meta.piece_length + begin;
char * content = torrent_get_bytes(p->tp, cbegin, length);
peer_send(p, nb_create_piece(index, begin, length));
peer_send(p, nb_create_torrentdata(content, length));
p->npiece_msgs++;
if (p->npiece_msgs >= MAXPIECEMSGS) {
peer_send(p, nb_create_choke());
peer_send(p, nb_create_unchoke());
p->flags |= PF_NO_REQUESTS;
}
}
}

@@ -475,18 +475,18 @@ peer_on_cancel(struct peer *p, uint32_t index, uint32_t begin,
uint32_t length)
{
btpd_log(BTPD_L_MSG, "received cancel(%u,%u,%u) from %p\n",
index, begin, length, p);
index, begin, length, p);
struct nb_link *nl;
BTPDQ_FOREACH(nl, &p->outq, entry)
if (nl->nb->type == NB_PIECE
&& nb_get_begin(nl->nb) == begin
&& nb_get_index(nl->nb) == index
&& nb_get_length(nl->nb) == length) {
struct nb_link *data = BTPDQ_NEXT(nl, entry);
if (peer_unsend(p, nl))
peer_unsend(p, data);
break;
}
if (nl->nb->type == NB_PIECE
&& nb_get_begin(nl->nb) == begin
&& nb_get_index(nl->nb) == index
&& nb_get_length(nl->nb) == length) {
struct nb_link *data = BTPDQ_NEXT(nl, entry);
if (peer_unsend(p, nl))
peer_unsend(p, data);
break;
}
}

int
@@ -529,5 +529,5 @@ int
peer_active_up(struct peer *p)
{
return (p->flags & (PF_P_WANT|PF_I_CHOKE)) == PF_P_WANT
|| p->npiece_msgs > 0;
|| p->npiece_msgs > 0;
}

+ 12
- 12
btpd/peer.h 파일 보기

@@ -1,16 +1,16 @@
#ifndef BTPD_PEER_H
#define BTPD_PEER_H

#define PF_I_WANT 0x1 /* We want to download from the peer */
#define PF_I_CHOKE 0x2 /* We choke the peer */
#define PF_P_WANT 0x4 /* The peer wants to download from us */
#define PF_P_CHOKE 0x8 /* The peer is choking us */
#define PF_ON_READQ 0x10
#define PF_ON_WRITEQ 0x20
#define PF_ATTACHED 0x40
#define PF_NO_REQUESTS 0x80
#define PF_INCOMING 0x100
#define PF_DO_UNWANT 0x200
#define PF_I_WANT 0x1 /* We want to download from the peer */
#define PF_I_CHOKE 0x2 /* We choke the peer */
#define PF_P_WANT 0x4 /* The peer wants to download from us */
#define PF_P_CHOKE 0x8 /* The peer is choking us */
#define PF_ON_READQ 0x10
#define PF_ON_WRITEQ 0x20
#define PF_ATTACHED 0x40
#define PF_NO_REQUESTS 0x80
#define PF_INCOMING 0x100
#define PF_DO_UNWANT 0x200

#define MAXPIECEMSGS 128
#define MAXPIPEDREQUESTS 10
@@ -52,8 +52,8 @@ struct peer {
struct {
uint32_t msg_len;
uint8_t msg_num;
uint32_t pc_index;
uint32_t pc_begin;
uint32_t pc_index;
uint32_t pc_begin;
enum net_state state;
size_t st_bytes;
char *buf;


+ 60
- 60
btpd/queue.h 파일 보기

@@ -1,5 +1,5 @@
/*
* @(#)queue.h 8.5 (Berkeley) 8/20/94
* @(#)queue.h 8.5 (Berkeley) 8/20/94
* $FreeBSD: src/sys/sys/queue.h,v 1.58.2.1 2005/01/31 23:26:57 imp Exp $
*/

@@ -9,86 +9,86 @@
/*
* Tail queue declarations.
*/
#define BTPDQ_HEAD(name, type) \
struct name { \
struct type *tqh_first; /* first element */ \
struct type **tqh_last; /* addr of last next element */ \
#define BTPDQ_HEAD(name, type) \
struct name { \
struct type *tqh_first; /* first element */ \
struct type **tqh_last; /* addr of last next element */ \
}

#define BTPDQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).tqh_first }
#define BTPDQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).tqh_first }

#define BTPDQ_ENTRY(type) \
struct { \
struct type *tqe_next; /* next element */ \
struct type **tqe_prev; /* address of previous next element */ \
#define BTPDQ_ENTRY(type) \
struct { \
struct type *tqe_next; /* next element */ \
struct type **tqe_prev; /* address of previous next element */ \
}

#define BTPDQ_EMPTY(head) ((head)->tqh_first == NULL)
#define BTPDQ_EMPTY(head) ((head)->tqh_first == NULL)

#define BTPDQ_FIRST(head) ((head)->tqh_first)
#define BTPDQ_FIRST(head) ((head)->tqh_first)

#define BTPDQ_LAST(head, headname) \
(*(((struct headname *)((head)->tqh_last))->tqh_last))
#define BTPDQ_LAST(head, headname) \
(*(((struct headname *)((head)->tqh_last))->tqh_last))

#define BTPDQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define BTPDQ_NEXT(elm, field) ((elm)->field.tqe_next)

#define BTPDQ_PREV(elm, headname, field) \
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
#define BTPDQ_PREV(elm, headname, field) \
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))

#define BTPDQ_FOREACH(var, head, field) \
for ((var) = BTPDQ_FIRST((head)); \
(var); \
(var) = BTPDQ_NEXT((var), field))
#define BTPDQ_FOREACH(var, head, field) \
for ((var) = BTPDQ_FIRST((head)); \
(var); \
(var) = BTPDQ_NEXT((var), field))

#define BTPDQ_INIT(head) do { \
BTPDQ_FIRST((head)) = NULL; \
(head)->tqh_last = &BTPDQ_FIRST((head)); \
#define BTPDQ_INIT(head) do { \
BTPDQ_FIRST((head)) = NULL; \
(head)->tqh_last = &BTPDQ_FIRST((head)); \
} while (0)

#define BTPDQ_INSERT_AFTER(head, listelm, elm, field) do { \
if ((BTPDQ_NEXT((elm), field) = BTPDQ_NEXT((listelm), field)) != NULL)\
BTPDQ_NEXT((elm), field)->field.tqe_prev = \
&BTPDQ_NEXT((elm), field); \
else { \
(head)->tqh_last = &BTPDQ_NEXT((elm), field); \
} \
BTPDQ_NEXT((listelm), field) = (elm); \
(elm)->field.tqe_prev = &BTPDQ_NEXT((listelm), field); \
#define BTPDQ_INSERT_AFTER(head, listelm, elm, field) do { \
if ((BTPDQ_NEXT((elm), field) = BTPDQ_NEXT((listelm), field)) != NULL)\
BTPDQ_NEXT((elm), field)->field.tqe_prev = \
&BTPDQ_NEXT((elm), field); \
else { \
(head)->tqh_last = &BTPDQ_NEXT((elm), field); \
} \
BTPDQ_NEXT((listelm), field) = (elm); \
(elm)->field.tqe_prev = &BTPDQ_NEXT((listelm), field); \
} while (0)

#define BTPDQ_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
BTPDQ_NEXT((elm), field) = (listelm); \
*(listelm)->field.tqe_prev = (elm); \
(listelm)->field.tqe_prev = &BTPDQ_NEXT((elm), field); \
#define BTPDQ_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
BTPDQ_NEXT((elm), field) = (listelm); \
*(listelm)->field.tqe_prev = (elm); \
(listelm)->field.tqe_prev = &BTPDQ_NEXT((elm), field); \
} while (0)

#define BTPDQ_INSERT_HEAD(head, elm, field) do { \
if ((BTPDQ_NEXT((elm), field) = BTPDQ_FIRST((head))) != NULL) \
BTPDQ_FIRST((head))->field.tqe_prev = \
&BTPDQ_NEXT((elm), field); \
else \
(head)->tqh_last = &BTPDQ_NEXT((elm), field); \
BTPDQ_FIRST((head)) = (elm); \
(elm)->field.tqe_prev = &BTPDQ_FIRST((head)); \
#define BTPDQ_INSERT_HEAD(head, elm, field) do { \
if ((BTPDQ_NEXT((elm), field) = BTPDQ_FIRST((head))) != NULL) \
BTPDQ_FIRST((head))->field.tqe_prev = \
&BTPDQ_NEXT((elm), field); \
else \
(head)->tqh_last = &BTPDQ_NEXT((elm), field); \
BTPDQ_FIRST((head)) = (elm); \
(elm)->field.tqe_prev = &BTPDQ_FIRST((head)); \
} while (0)

#define BTPDQ_INSERT_TAIL(head, elm, field) do { \
BTPDQ_NEXT((elm), field) = NULL; \
(elm)->field.tqe_prev = (head)->tqh_last; \
*(head)->tqh_last = (elm); \
(head)->tqh_last = &BTPDQ_NEXT((elm), field); \
#define BTPDQ_INSERT_TAIL(head, elm, field) do { \
BTPDQ_NEXT((elm), field) = NULL; \
(elm)->field.tqe_prev = (head)->tqh_last; \
*(head)->tqh_last = (elm); \
(head)->tqh_last = &BTPDQ_NEXT((elm), field); \
} while (0)

#define BTPDQ_REMOVE(head, elm, field) do { \
if ((BTPDQ_NEXT((elm), field)) != NULL) \
BTPDQ_NEXT((elm), field)->field.tqe_prev = \
(elm)->field.tqe_prev; \
else { \
(head)->tqh_last = (elm)->field.tqe_prev; \
} \
*(elm)->field.tqe_prev = BTPDQ_NEXT((elm), field); \
#define BTPDQ_REMOVE(head, elm, field) do { \
if ((BTPDQ_NEXT((elm), field)) != NULL) \
BTPDQ_NEXT((elm), field)->field.tqe_prev = \
(elm)->field.tqe_prev; \
else { \
(head)->tqh_last = (elm)->field.tqe_prev; \
} \
*(elm)->field.tqe_prev = BTPDQ_NEXT((elm), field); \
} while (0)

#endif

+ 50
- 50
btpd/torrent.c 파일 보기

@@ -40,7 +40,7 @@ torrent_load3(const char *file, struct metainfo *mi, char *mem, size_t memsiz)

tp->relpath = strdup(file);
if (tp->relpath == NULL)
btpd_err("Out of memory.\n");
btpd_err("Out of memory.\n");

tp->piece_count = btpd_calloc(mi->npieces, sizeof(tp->piece_count[0]));
tp->busy_field = btpd_calloc(ceil(mi->npieces / 8.0), 1);
@@ -53,11 +53,11 @@ torrent_load3(const char *file, struct metainfo *mi, char *mem, size_t memsiz)

tp->piece_field = tp->imem;
tp->block_field =
(uint8_t *)tp->imem + (size_t)ceil(mi->npieces / 8.0);
(uint8_t *)tp->imem + (size_t)ceil(mi->npieces / 8.0);

for (uint32_t i = 0; i < mi->npieces; i++)
if (has_bit(tp->piece_field, i))
tp->have_npieces++;
if (has_bit(tp->piece_field, i))
tp->have_npieces++;

tp->meta = *mi;
free(mi);
@@ -80,38 +80,38 @@ torrent_load2(const char *name, struct metainfo *mi)
const char *file = name;

if ((error = vopen(&ifd, O_RDWR, "%s/resume", file)) != 0) {
btpd_log(BTPD_L_ERROR, "Error opening %s.i: %s.\n",
file, strerror(error));
return error;
btpd_log(BTPD_L_ERROR, "Error opening %s.i: %s.\n",
file, strerror(error));
return error;
}

if (fstat(ifd, &sb) == -1) {
error = errno;
btpd_log(BTPD_L_ERROR, "Error stating %s.i: %s.\n",
file, strerror(error));
close(ifd);
return error;
error = errno;
btpd_log(BTPD_L_ERROR, "Error stating %s.i: %s.\n",
file, strerror(error));
close(ifd);
return error;
}

memsiz =
ceil(mi->npieces / 8.0) +
mi->npieces * ceil(mi->piece_length / (double)(1 << 17));
ceil(mi->npieces / 8.0) +
mi->npieces * ceil(mi->piece_length / (double)(1 << 17));

if (sb.st_size != memsiz) {
btpd_log(BTPD_L_ERROR, "File has wrong size: %s.i.\n", file);
close(ifd);
return EINVAL;
btpd_log(BTPD_L_ERROR, "File has wrong size: %s.i.\n", file);
close(ifd);
return EINVAL;
}

mem = mmap(NULL, memsiz, PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0);
if (mem == MAP_FAILED)
btpd_err("Error mmap'ing %s.i: %s.\n", file, strerror(errno));
btpd_err("Error mmap'ing %s.i: %s.\n", file, strerror(errno));

close(ifd);

if ((error = torrent_load3(file, mi, mem, memsiz) != 0)) {
munmap(mem, memsiz);
return error;
munmap(mem, memsiz);
return error;
}

return 0;
@@ -126,22 +126,22 @@ torrent_load(const char *name)
snprintf(file, PATH_MAX, "%s/torrent", name);

if ((error = load_metainfo(file, -1, 0, &mi)) != 0) {
btpd_log(BTPD_L_ERROR, "Couldn't load metainfo file %s: %s.\n",
file, strerror(error));
return error;
btpd_log(BTPD_L_ERROR, "Couldn't load metainfo file %s: %s.\n",
file, strerror(error));
return error;
}

if (btpd_get_torrent(mi->info_hash) != NULL) {
btpd_log(BTPD_L_BTPD, "%s has same hash as an already loaded torrent.\n", file);
error = EEXIST;
btpd_log(BTPD_L_BTPD, "%s has same hash as an already loaded torrent.\n", file);
error = EEXIST;
}

if (error == 0)
error = torrent_load2(name, mi);
error = torrent_load2(name, mi);

if (error != 0) {
clear_metainfo(mi);
free(mi);
clear_metainfo(mi);
free(mi);
}

return error;
@@ -171,14 +171,14 @@ off_t
torrent_bytes_left(struct torrent *tp)
{
if (tp->have_npieces == 0)
return tp->meta.total_length;
return tp->meta.total_length;
else if (has_bit(tp->piece_field, tp->meta.npieces - 1)) {
return tp->meta.total_length -
((tp->have_npieces - 1) * tp->meta.piece_length +
tp->meta.total_length % tp->meta.piece_length);
return tp->meta.total_length -
((tp->have_npieces - 1) * tp->meta.piece_length +
tp->meta.total_length % tp->meta.piece_length);
} else
return tp->meta.total_length -
tp->have_npieces * tp->meta.piece_length;
return tp->meta.total_length -
tp->have_npieces * tp->meta.piece_length;
}

char *
@@ -187,9 +187,9 @@ torrent_get_bytes(struct torrent *tp, off_t start, size_t len)
char *buf = btpd_malloc(len);
struct bt_stream_ro *bts;
if ((bts = bts_open_ro(&tp->meta, start, ro_fd_cb, tp)) == NULL)
btpd_err("Out of memory.\n");
btpd_err("Out of memory.\n");
if (bts_read_ro(bts, buf, len) != 0)
btpd_err("Io error.\n");
btpd_err("Io error.\n");
bts_close_ro(bts);
return buf;
}
@@ -200,11 +200,11 @@ torrent_put_bytes(struct torrent *tp, const char *buf, off_t start, size_t len)
int err;
struct bt_stream_wo *bts;
if ((bts = bts_open_wo(&tp->meta, start, wo_fd_cb, tp)) == NULL)
btpd_err("Out of memory.\n");
btpd_err("Out of memory.\n");
if ((err = bts_write_wo(bts, buf, len)) != 0)
btpd_err("Io error1: %s\n", strerror(err));
btpd_err("Io error1: %s\n", strerror(err));
if ((err = bts_close_wo(bts)) != 0)
btpd_err("Io error2: %s\n", strerror(err));
btpd_err("Io error2: %s\n", strerror(err));
}

int
@@ -213,11 +213,11 @@ torrent_has_peer(struct torrent *tp, const uint8_t *id)
int has = 0;
struct peer *p = BTPDQ_FIRST(&tp->peers);
while (p != NULL) {
if (bcmp(p->id, id, 20) == 0) {
has = 1;
break;
}
p = BTPDQ_NEXT(p, p_entry);
if (bcmp(p->id, id, 20) == 0) {
has = 1;
break;
}
p = BTPDQ_NEXT(p, p_entry);
}
return has;
}
@@ -226,10 +226,10 @@ off_t
torrent_piece_size(struct torrent *tp, uint32_t index)
{
if (index < tp->meta.npieces - 1)
return tp->meta.piece_length;
return tp->meta.piece_length;
else {
off_t allbutlast = tp->meta.piece_length * (tp->meta.npieces - 1);
return tp->meta.total_length - allbutlast;
off_t allbutlast = tp->meta.piece_length * (tp->meta.npieces - 1);
return tp->meta.total_length - allbutlast;
}
}

@@ -237,10 +237,10 @@ uint32_t
torrent_block_size(struct piece *pc, uint32_t index)
{
if (index < pc->nblocks - 1)
return PIECE_BLOCKLEN;
return PIECE_BLOCKLEN;
else {
uint32_t allbutlast = PIECE_BLOCKLEN * (pc->nblocks - 1);
return torrent_piece_size(pc->tp, pc->index) - allbutlast;
uint32_t allbutlast = PIECE_BLOCKLEN * (pc->nblocks - 1);
return torrent_piece_size(pc->tp, pc->index) - allbutlast;
}
}



+ 2
- 2
btpd/torrent.h 파일 보기

@@ -52,7 +52,7 @@ struct torrent {
unsigned *piece_count;

uint64_t uploaded, downloaded;
unsigned npeers;
struct peer_tq peers;

@@ -66,7 +66,7 @@ off_t torrent_bytes_left(struct torrent *tp);

char *torrent_get_bytes(struct torrent *tp, off_t start, size_t len);
void torrent_put_bytes(struct torrent *tp, const char *buf,
off_t start, size_t len);
off_t start, size_t len);

int torrent_load(const char *metafile);



+ 87
- 87
btpd/tracker_req.c 파일 보기

@@ -38,28 +38,28 @@ maybe_connect_to(struct torrent *tp, const char *pinfo)
size_t len;

if (!benc_isdct(pinfo))
return;
return;

if (benc_dget_str(pinfo, "peer id", &pid, &len) != 0 || len != 20)
return;
return;

if (bcmp(btpd_get_peer_id(), pid, 20) == 0)
return;
return;

if (torrent_has_peer(tp, pid))
return;
return;

if (benc_dget_strz(pinfo, "ip", &ip, NULL) != 0)
goto out;
goto out;

if (benc_dget_int64(pinfo, "port", &port) != 0)
goto out;
goto out;

peer_create_out(tp, pid, ip, port);

out:
if (ip != NULL)
free(ip);
free(ip);
}

static void
@@ -73,31 +73,31 @@ tracker_done(pid_t pid, void *arg)
struct torrent *tp;

if ((tp = btpd_get_torrent(req->info_hash)) == NULL)
goto out;
goto out;

if (benc_validate(req->res->buf, req->res->buf_off) != 0
|| !benc_isdct(req->res->buf)) {
if (req->res->buf_off != 0) {
fwrite(req->res->buf, 1, req->res->buf_off, (stdout));
putchar('\n');
}
btpd_log(BTPD_L_ERROR, "Bad data from tracker.\n");
failed = 1;
goto out;
|| !benc_isdct(req->res->buf)) {
if (req->res->buf_off != 0) {
fwrite(req->res->buf, 1, req->res->buf_off, (stdout));
putchar('\n');
}
btpd_log(BTPD_L_ERROR, "Bad data from tracker.\n");
failed = 1;
goto out;
}

if ((benc_dget_strz(req->res->buf, "failure reason", &buf, NULL)) == 0) {
btpd_log(BTPD_L_ERROR, "Tracker failure: %s.\n", buf);
free(buf);
failed = 1;
goto out;
btpd_log(BTPD_L_ERROR, "Tracker failure: %s.\n", buf);
free(buf);
failed = 1;
goto out;
}

if ((benc_dget_uint32(req->res->buf, "interval", &interval)) != 0) {
btpd_log(BTPD_L_ERROR, "Bad data from tracker.\n");
failed = 1;
goto out;
btpd_log(BTPD_L_ERROR, "Bad data from tracker.\n");
failed = 1;
goto out;
}

//tp->tracker_time = btpd_seconds + interval;
@@ -106,34 +106,34 @@ tracker_done(pid_t pid, void *arg)
size_t length;

if ((error = benc_dget_lst(req->res->buf, "peers", &peers)) == 0) {
for (peers = benc_first(peers);
peers != NULL && net_npeers < net_max_peers;
peers = benc_next(peers))
maybe_connect_to(tp, peers);
for (peers = benc_first(peers);
peers != NULL && net_npeers < net_max_peers;
peers = benc_next(peers))
maybe_connect_to(tp, peers);
}

if (error == EINVAL) {
error = benc_dget_str(req->res->buf, "peers", &peers, &length);
if (error == 0 && length % 6 == 0) {
error = benc_dget_str(req->res->buf, "peers", &peers, &length);
if (error == 0 && length % 6 == 0) {
size_t i;
for (i = 0; i < length && net_npeers < net_max_peers; i += 6)
peer_create_out_compact(tp, peers + i);
}
peer_create_out_compact(tp, peers + i);
}
}

if (error != 0) {
btpd_log(BTPD_L_ERROR, "Bad data from tracker.\n");
failed = 1;
goto out;
btpd_log(BTPD_L_ERROR, "Bad data from tracker.\n");
failed = 1;
goto out;
}

out:
if (failed) {
if (req->tr_event == TR_STARTED) {
btpd_log(BTPD_L_BTPD,
"Start request failed for %s.\n", tp->relpath);
torrent_unload(tp);
} else
if (req->tr_event == TR_STARTED) {
btpd_log(BTPD_L_BTPD,
"Start request failed for %s.\n", tp->relpath);
torrent_unload(tp);
} else
;//tp->tracker_time = btpd_seconds + 10;
}
munmap(req->res, REQ_SIZE);
@@ -145,16 +145,16 @@ event2str(enum tr_event ev)
{
switch (ev) {
case TR_STARTED:
return "started";
return "started";
case TR_STOPPED:
return "stopped";
return "stopped";
case TR_COMPLETED:
return "completed";
return "completed";
case TR_EMPTY:
return "";
return "";
default:
btpd_err("Bad tracker event %d.\n", ev);
return ""; // Shut GCC up!
btpd_err("Bad tracker event %d.\n", ev);
return ""; // Shut GCC up!
}
}

@@ -173,28 +173,28 @@ create_url(struct tracker_req *req, struct torrent *tp, char **url)
qc = (strchr(tp->meta.announce, '?') == NULL) ? '?' : '&';

for (i = 0; i < 20; i++)
snprintf(e_hash + i * 3, 4, "%%%.2x", tp->meta.info_hash[i]);
snprintf(e_hash + i * 3, 4, "%%%.2x", tp->meta.info_hash[i]);

for (i = 0; i < 20; i++)
snprintf(e_id + i * 3, 4, "%%%.2x", peer_id[i]);
snprintf(e_id + i * 3, 4, "%%%.2x", peer_id[i]);

left = torrent_bytes_left(tp);

i = asprintf(url, "%s%cinfo_hash=%s"
"&peer_id=%s"
"&port=%d"
"&uploaded=%" PRIu64
"&downloaded=%" PRIu64
"&left=%" PRIu64
"&compact=1"
"%s%s",
tp->meta.announce, qc, e_hash, e_id, net_port,
tp->uploaded, tp->downloaded, left,
req->tr_event == TR_EMPTY ? "" : "&event=",
event);
"&peer_id=%s"
"&port=%d"
"&uploaded=%" PRIu64
"&downloaded=%" PRIu64
"&left=%" PRIu64
"&compact=1"
"%s%s",
tp->meta.announce, qc, e_hash, e_id, net_port,
tp->uploaded, tp->downloaded, left,
req->tr_event == TR_EMPTY ? "" : "&event=",
event);

if (i < 0)
return ENOMEM;
return ENOMEM;
return 0;
}

@@ -204,12 +204,12 @@ http_cb(void *ptr, size_t size, size_t nmemb, void *stream)
struct tracker_req *req = (struct tracker_req *)stream;
size_t nbytes = size * nmemb;
if (nbytes <= req->res->buf_len - req->res->buf_off) {
memcpy(req->res->buf + req->res->buf_off, ptr, nbytes);
req->res->buf_off += nbytes;
return nbytes;
memcpy(req->res->buf + req->res->buf_off, ptr, nbytes);
req->res->buf_off += nbytes;
return nbytes;
}
else
return 0;
return 0;
}

static void
@@ -222,31 +222,31 @@ http_helper(struct tracker_req *req, struct torrent *tp)
int err;

if (create_url(req, tp, &url) != 0)
goto memory_error;
goto memory_error;

if (curl_global_init(0) != 0)
goto libcurl_error;
goto libcurl_error;
if ((handle = curl_easy_init()) == NULL)
goto libcurl_error;
goto libcurl_error;

err = curl_easy_setopt(handle, CURLOPT_URL, url);
if (err == 0)
err = curl_easy_setopt(handle, CURLOPT_USERAGENT, BTPD_VERSION);
err = curl_easy_setopt(handle, CURLOPT_USERAGENT, BTPD_VERSION);
if (err == 0)
err = curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, http_cb);
err = curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, http_cb);
if (err == 0)
err = curl_easy_setopt(handle, CURLOPT_WRITEDATA, req);
err = curl_easy_setopt(handle, CURLOPT_WRITEDATA, req);
if (err == 0)
err = curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, cerror);
err = curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, cerror);
if (err != 0) {
strncpy(cerror, curl_easy_strerror(err), CURL_ERROR_SIZE - 1);
goto handle_error;
strncpy(cerror, curl_easy_strerror(err), CURL_ERROR_SIZE - 1);
goto handle_error;
}

req->res->buf_off = 0;
if (curl_easy_perform(handle) != 0)
goto handle_error;
goto handle_error;

#if 0
curl_easy_cleanup(handle);
@@ -263,12 +263,12 @@ libcurl_error:
strncpy(cerror, "Generic libcurl error", CURL_ERROR_SIZE - 1);
goto handle_error;

handle_error:
handle_error:
req->res->buf_off =
snprintf(req->res->buf, req->res->buf_len,
"d%d:%s%d:%se", (int)strlen(fr), fr, (int)strlen(cerror), cerror);
snprintf(req->res->buf, req->res->buf_len,
"d%d:%s%d:%se", (int)strlen(fr), fr, (int)strlen(cerror), cerror);
if (req->res->buf_off >= req->res->buf_len)
req->res->buf_off = 0;
req->res->buf_off = 0;

exit(1);
}
@@ -281,7 +281,7 @@ tracker_req(struct torrent *tp, enum tr_event tr_event)

btpd_log(BTPD_L_TRACKER,
"request for %s, event: %s.\n",
tp->relpath, event2str(tr_event));
tp->relpath, event2str(tr_event));

req = (struct tracker_req *)btpd_calloc(1, sizeof(*req));

@@ -289,7 +289,7 @@ tracker_req(struct torrent *tp, enum tr_event tr_event)
MAP_ANON | MAP_SHARED, -1, 0);

if (req->res == MAP_FAILED)
btpd_err("Failed mmap: %s\n", strerror(errno));
btpd_err("Failed mmap: %s\n", strerror(errno));

req->res->buf_len = REQ_SIZE - sizeof(*req->res);
req->res->buf_off = 0;
@@ -302,12 +302,12 @@ tracker_req(struct torrent *tp, enum tr_event tr_event)

pid = fork();
if (pid < 0) {
btpd_err("Couldn't fork (%s).\n", strerror(errno));
btpd_err("Couldn't fork (%s).\n", strerror(errno));
} else if (pid == 0) { // Child
int nfiles = getdtablesize();
for (int i = 0; i < nfiles; i++)
close(i);
http_helper(req, tp);
int nfiles = getdtablesize();
for (int i = 0; i < nfiles; i++)
close(i);
http_helper(req, tp);
} else
btpd_add_child(pid, tracker_done, req);
btpd_add_child(pid, tracker_done, req);
}

+ 6
- 6
btpd/upload.c 파일 보기

@@ -11,7 +11,7 @@ choke_do(void)
struct peer *p;
BTPDQ_FOREACH(p, &m_peerq, ul_entry)
if (p->flags & PF_I_CHOKE)
peer_unchoke(p);
peer_unchoke(p);
}

static void
@@ -36,7 +36,7 @@ ul_on_lost_peer(struct peer *p)
BTPDQ_REMOVE(&m_peerq, p, ul_entry);
m_npeers--;
if ((p->flags & (PF_P_WANT|PF_I_CHOKE)) == PF_P_WANT)
choke_do();
choke_do();
}

void
@@ -44,8 +44,8 @@ ul_on_lost_torrent(struct torrent *tp)
{
struct peer *p;
BTPDQ_FOREACH(p, &tp->peers, p_entry) {
BTPDQ_REMOVE(&m_peerq, p, ul_entry);
m_npeers--;
BTPDQ_REMOVE(&m_peerq, p, ul_entry);
m_npeers--;
}
choke_do();
}
@@ -54,14 +54,14 @@ void
ul_on_interest(struct peer *p)
{
if ((p->flags & PF_I_CHOKE) == 0)
choke_do();
choke_do();
}

void
ul_on_uninterest(struct peer *p)
{
if ((p->flags & PF_I_CHOKE) == 0)
choke_do();
choke_do();
}

void


+ 18
- 18
btpd/util.c 파일 보기

@@ -8,7 +8,7 @@ btpd_malloc(size_t size)
{
void *a;
if ((a = malloc(size)) == NULL)
btpd_err("Failed to allocate %d bytes.\n", (int)size);
btpd_err("Failed to allocate %d bytes.\n", (int)size);
return a;
}

@@ -17,7 +17,7 @@ btpd_calloc(size_t nmemb, size_t size)
{
void *a;
if ((a = calloc(nmemb, size)) == NULL)
btpd_err("Failed to allocate %d bytes.\n", (int)(nmemb * size));
btpd_err("Failed to allocate %d bytes.\n", (int)(nmemb * size));
return a;
}

@@ -25,17 +25,17 @@ static const char *
logtype_str(uint32_t type)
{
if (type & BTPD_L_BTPD)
return "btpd";
return "btpd";
else if (type & BTPD_L_ERROR)
return "error";
return "error";
else if (type & BTPD_L_CONN)
return "conn";
return "conn";
else if (type & BTPD_L_TRACKER)
return "tracker";
return "tracker";
else if (type & BTPD_L_MSG)
return "msg";
return "msg";
else
return "";
return "";
}

void
@@ -44,11 +44,11 @@ btpd_err(const char *fmt, ...)
va_list ap;
va_start(ap, fmt);
if (BTPD_L_ERROR & btpd_logmask) {
char tbuf[20];
time_t tp = time(NULL);
strftime(tbuf, 20, "%b %e %T", localtime(&tp));
printf("%s %s: ", tbuf, logtype_str(BTPD_L_ERROR));
vprintf(fmt, ap);
char tbuf[20];
time_t tp = time(NULL);
strftime(tbuf, 20, "%b %e %T", localtime(&tp));
printf("%s %s: ", tbuf, logtype_str(BTPD_L_ERROR));
vprintf(fmt, ap);
}
va_end(ap);
exit(1);
@@ -60,11 +60,11 @@ btpd_log(uint32_t type, const char *fmt, ...)
va_list ap;
va_start(ap, fmt);
if (type & btpd_logmask) {
char tbuf[20];
time_t tp = time(NULL);
strftime(tbuf, 20, "%b %e %T", localtime(&tp));
printf("%s %s: ", tbuf, logtype_str(type));
vprintf(fmt, ap);
char tbuf[20];
time_t tp = time(NULL);
strftime(tbuf, 20, "%b %e %T", localtime(&tp));
printf("%s %s: ", tbuf, logtype_str(type));
vprintf(fmt, ap);
}
va_end(ap);
}

+ 125
- 125
cli/btcli.c 파일 보기

@@ -24,16 +24,16 @@ static void
usage()
{
printf("Usage: btcli command [options] [files]\n"
"Commands:\n"
"add <file_1> ... [file_n]\n"
"\tAdd the given torrents to btpd.\n"
"\n"
"del <file_1> ... [file_n]\n"
"\tRemove the given torrents from btpd.\n"
"\n"
"die\n"
"\tShut down btpd.\n"
"\n"
"Commands:\n"
"add <file_1> ... [file_n]\n"
"\tAdd the given torrents to btpd.\n"
"\n"
"del <file_1> ... [file_n]\n"
"\tRemove the given torrents from btpd.\n"
"\n"
"die\n"
"\tShut down btpd.\n"
"\n"
"list\n"
"\tList active torrents.\n"
"\n"
@@ -47,13 +47,13 @@ usage()
"-w n\n"
"\tRepeat every n seconds.\n"
"\n"
"Common options:\n"
"--ipc key\n"
"\tTalk to the btpd started with the same key.\n"
"\n"
"--help\n"
"\tShow this help.\n"
"\n");
"Common options:\n"
"--ipc key\n"
"\tTalk to the btpd started with the same key.\n"
"\n"
"--help\n"
"\tShow this help.\n"
"\n");
exit(1);
}

@@ -62,12 +62,12 @@ handle_error(int error)
{
switch (error) {
case 0:
break;
break;
case ENOENT:
case ECONNREFUSED:
errx(1, "Couldn't connect. Check that btpd is running.");
errx(1, "Couldn't connect. Check that btpd is running.");
default:
errx(1, "%s", strerror(error));
errx(1, "%s", strerror(error));
}
}

@@ -76,11 +76,11 @@ do_ipc_open(char *ipctok, struct ipc **ipc)
{
switch (ipc_open(ipctok, ipc)) {
case 0:
break;
break;
case EINVAL:
errx(1, "--ipc argument only takes letters and digits.");
errx(1, "--ipc argument only takes letters and digits.");
case ENAMETOOLONG:
errx(1, "--ipc argument is too long.");
errx(1, "--ipc argument is too long.");
}
}

@@ -96,10 +96,10 @@ hash_cb(uint32_t index, uint8_t *hash, void *arg)
{
struct cb *cb = arg;
if (hash != NULL)
if (bcmp(hash, cb->meta->piece_hash[index], SHA_DIGEST_LENGTH) == 0) {
set_bit(cb->piece_field, index);
if (bcmp(hash, cb->meta->piece_hash[index], SHA_DIGEST_LENGTH) == 0) {
set_bit(cb->piece_field, index);
cb->have++;
}
}
printf("\rTested: %5.1f%%", 100.0 * (index + 1) / cb->meta->npieces);
fflush(stdout);
}
@@ -120,7 +120,7 @@ gen_ifile(char *path)
size_t field_len;

if ((errno = load_metainfo(path, -1, 1, &mi)) != 0)
err(1, "load_metainfo: %s", path);
err(1, "load_metainfo: %s", path);

field_len = ceil(mi->npieces / 8.0);
cb.path = path;
@@ -129,24 +129,24 @@ gen_ifile(char *path)
cb.meta = mi;

if (cb.piece_field == NULL)
errx(1, "Out of memory.\n");
errx(1, "Out of memory.\n");

if ((errno = bts_hashes(mi, fd_cb, hash_cb, &cb)) != 0)
err(1, "bts_hashes");
err(1, "bts_hashes");
printf("\nHave: %5.1f%%\n", 100.0 * cb.have / cb.meta->npieces);

if ((errno = vopen(&fd, O_WRONLY|O_CREAT, "%s.i", path)) != 0)
err(1, "opening %s.i", path);
err(1, "opening %s.i", path);

if (ftruncate(fd, field_len + mi->npieces *
(off_t)ceil(mi->piece_length / (double)(1 << 17))) < 0)
err(1, "ftruncate: %s", path);
(off_t)ceil(mi->piece_length / (double)(1 << 17))) < 0)
err(1, "ftruncate: %s", path);

if (write(fd, cb.piece_field, field_len) != field_len)
err(1, "write %s.i", path);
err(1, "write %s.i", path);

if (close(fd) < 0)
err(1, "close %s.i", path);
err(1, "close %s.i", path);

clear_metainfo(mi);
free(mi);
@@ -173,45 +173,45 @@ cmd_add(int argc, char **argv)
int ch;
char *ipctok = NULL;
while ((ch = getopt_long(argc, argv, "", add_opts, NULL)) != -1) {
switch(ch) {
case 1:
ipctok = optarg;
break;
default:
usage();
}
switch(ch) {
case 1:
ipctok = optarg;
break;
default:
usage();
}
}
argc -= optind;
argv += optind;

if (argc < 1)
usage();
usage();

for (int i = 0; i < argc; i++) {
int64_t code;
char *res;
int fd;
char *path;
errno = vopen(&fd, O_RDONLY, "%s.i", argv[i]);
if (errno == ENOENT) {
printf("Testing %s for content.\n", argv[i]);
gen_ifile(argv[i]);
} else if (errno != 0)
err(1, "open %s.i", argv[i]);
else
close(fd);
if ((errno = canon_path(argv[i], &path)) != 0)
err(1, "canon_path");
do_add(ipctok, &path, 1, &res);
free(path);
benc_dget_int64(benc_first(res), "code", &code);
if (code == EEXIST)
printf("btpd already had %s.\n", argv[i]);
else if (code != 0) {
printf("btpd indicates error: %s for %s.\n",
strerror(code), argv[i]);
}
int64_t code;
char *res;
int fd;
char *path;
errno = vopen(&fd, O_RDONLY, "%s.i", argv[i]);
if (errno == ENOENT) {
printf("Testing %s for content.\n", argv[i]);
gen_ifile(argv[i]);
} else if (errno != 0)
err(1, "open %s.i", argv[i]);
else
close(fd);
if ((errno = canon_path(argv[i], &path)) != 0)
err(1, "canon_path");
do_add(ipctok, &path, 1, &res);
free(path);
benc_dget_int64(benc_first(res), "code", &code);
if (code == EEXIST)
printf("btpd already had %s.\n", argv[i]);
else if (code != 0) {
printf("btpd indicates error: %s for %s.\n",
strerror(code), argv[i]);
}
free(res);
}
}
@@ -237,45 +237,45 @@ cmd_del(int argc, char **argv)
int ch;
char *ipctok = NULL;
while ((ch = getopt_long(argc, argv, "", del_opts, NULL)) != -1) {
switch(ch) {
case 1:
ipctok = optarg;
break;
default:
usage();
}
switch(ch) {
case 1:
ipctok = optarg;
break;
default:
usage();
}
}
argc -= optind;
argv += optind;

if (argc < 1)
usage();
usage();

uint8_t hashes[argc][20];
char *res;
const char *d;

for (int i = 0; i < argc; i++) {
struct metainfo *mi;
if ((errno = load_metainfo(argv[i], -1, 0, &mi)) != 0)
err(1, "load_metainfo: %s", argv[i]);
bcopy(mi->info_hash, hashes[i], 20);
clear_metainfo(mi);
free(mi);
struct metainfo *mi;
if ((errno = load_metainfo(argv[i], -1, 0, &mi)) != 0)
err(1, "load_metainfo: %s", argv[i]);
bcopy(mi->info_hash, hashes[i], 20);
clear_metainfo(mi);
free(mi);
}
do_del(ipctok, hashes, argc, &res);
d = benc_first(res);
for (int i = 0; i < argc; i++) {
int64_t code;
benc_dget_int64(d, "code", &code);
if (code == ENOENT)
printf("btpd didn't have %s.\n", argv[i]);
else if (code != 0) {
printf("btpd indicates error: %s for %s.\n",
strerror(code), argv[i]);
}
d = benc_next(d);
int64_t code;
benc_dget_int64(d, "code", &code);
if (code == ENOENT)
printf("btpd didn't have %s.\n", argv[i]);
else if (code != 0) {
printf("btpd indicates error: %s for %s.\n",
strerror(code), argv[i]);
}
d = benc_next(d);
}
free(res);
}
@@ -302,13 +302,13 @@ cmd_die(int argc, char **argv)
char *ipctok = NULL;

while ((ch = getopt_long(argc, argv, "", die_opts, NULL)) != -1) {
switch (ch) {
case 1:
ipctok = optarg;
break;
default:
usage();
}
switch (ch) {
case 1:
ipctok = optarg;
break;
default:
usage();
}
}
do_die(ipctok);
}
@@ -420,14 +420,14 @@ grok_stat(char *ipctok, int iflag, int wait,
again:
do_stat(ipctok, &res);
gettimeofday(&tv_cur, NULL);
if (old == NULL)
ds = wait;
if (old == NULL)
ds = wait;
else {
struct timeval delta;
timersub(&tv_old, &tv_cur, &delta);
ds = delta.tv_sec + delta.tv_usec / 1000000.0;
if (ds < 0)
ds = wait;
struct timeval delta;
timersub(&tv_old, &tv_cur, &delta);
ds = delta.tv_sec + delta.tv_usec / 1000000.0;
if (ds < 0)
ds = wait;
}
tv_old = tv_cur;
cur = parse_tors(res, hashes, nhashes);
@@ -484,7 +484,7 @@ cmd_stat(int argc, char **argv)
int iflag = 0;

while ((ch = getopt_long(argc, argv, "iw:", stat_opts, NULL)) != -1) {
switch (ch) {
switch (ch) {
case 'i':
iflag = 1;
break;
@@ -493,12 +493,12 @@ cmd_stat(int argc, char **argv)
if (wait <= 0)
errx(1, "-w argument must be an integer > 0.");
break;
case 1:
ipctok = optarg;
break;
default:
usage();
}
case 1:
ipctok = optarg;
break;
default:
usage();
}
}
argc -= optind;
argv += optind;
@@ -531,13 +531,13 @@ cmd_list(int argc, char **argv)
char *ipctok = NULL;

while ((ch = getopt_long(argc, argv, "", list_opts, NULL)) != -1) {
switch (ch) {
case 1:
ipctok = optarg;
break;
default:
usage();
}
switch (ch) {
case 1:
ipctok = optarg;
break;
default:
usage();
}
}
char *res;
const char *p;
@@ -572,18 +572,18 @@ int
main(int argc, char **argv)
{
if (argc < 2)
usage();
usage();
int found = 0;
for (int i = 0; !found && i < ncmds; i++) {
if (strcmp(argv[1], cmd_table[i].name) == 0) {
found = 1;
cmd_table[i].fun(argc - 1, argv + 1);
}
if (strcmp(argv[1], cmd_table[i].name) == 0) {
found = 1;
cmd_table[i].fun(argc - 1, argv + 1);
}
}

if (!found)
usage();
usage();

return 0;
}

+ 10
- 10
cli/btinfo.c 파일 보기

@@ -27,26 +27,26 @@ main(int argc, char **argv)
int ch;

while ((ch = getopt_long(argc, argv, "", longopts, NULL)) != -1)
usage();
usage();

argc -= optind;
argv += optind;

if (argc < 1)
usage();
usage();

while (argc > 0) {
struct metainfo *mi;
struct metainfo *mi;

if ((errno = load_metainfo(*argv, -1, 1, &mi)) != 0)
err(1, "load_metainfo: %s", *argv);
if ((errno = load_metainfo(*argv, -1, 1, &mi)) != 0)
err(1, "load_metainfo: %s", *argv);

print_metainfo(mi);
clear_metainfo(mi);
free(mi);
print_metainfo(mi);
clear_metainfo(mi);
free(mi);

argc--;
argv++;
argc--;
argv++;
}

return 0;


+ 36
- 36
cli/btpd_if.c 파일 보기

@@ -19,21 +19,21 @@ ipc_open(const char *key, struct ipc **out)
struct ipc *res;

if (key == NULL)
key = "default";
key = "default";
keylen = strlen(key);
for (int i = 0; i < keylen; i++)
if (!isalnum(key[i]))
return EINVAL;
if (!isalnum(key[i]))
return EINVAL;

res = malloc(sizeof(*res));
if (res == NULL)
return ENOMEM;
return ENOMEM;

plen = sizeof(res->addr.sun_path);
if (snprintf(res->addr.sun_path, plen,
"/tmp/btpd_%u_%s", geteuid(), key) >= plen) {
free(res);
return ENAMETOOLONG;
"/tmp/btpd_%u_%s", geteuid(), key) >= plen) {
free(res);
return ENAMETOOLONG;
}
res->addr.sun_family = AF_UNIX;
*out = res;
@@ -55,13 +55,13 @@ ipc_connect(struct ipc *ipc, FILE **out)
int error;

if ((sd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
return errno;
return errno;

if (connect(sd, (struct sockaddr *)&ipc->addr, sizeof(ipc->addr)) == -1)
goto error;
goto error;

if ((fp = fdopen(sd, "r+")) == NULL)
goto error;
goto error;

*out = fp;
return 0;
@@ -78,23 +78,23 @@ ipc_response(FILE *fp, char **out, uint32_t *len)
char *buf;

if (fread(&size, sizeof(size), 1, fp) != 1) {
if (ferror(fp))
return errno;
else
return ECONNRESET;
if (ferror(fp))
return errno;
else
return ECONNRESET;
}

if (size == 0)
return EINVAL;
return EINVAL;

if ((buf = malloc(size)) == NULL)
return ENOMEM;
return ENOMEM;

if (fread(buf, 1, size, fp) != size) {
if (ferror(fp))
return errno;
else
return ECONNRESET;
if (ferror(fp))
return errno;
else
return ECONNRESET;
}

*out = buf;
@@ -104,25 +104,25 @@ ipc_response(FILE *fp, char **out, uint32_t *len)

static int
ipc_req_res(struct ipc *ipc,
const char *req, uint32_t qlen,
char **res, uint32_t *rlen)
const char *req, uint32_t qlen,
char **res, uint32_t *rlen)
{
FILE *fp;
int error;

if ((error = ipc_connect(ipc, &fp)) != 0)
return error;
return error;

if (fwrite(&qlen, sizeof(qlen), 1, fp) != 1)
goto error;
goto error;
if (fwrite(req, 1, qlen, fp) != qlen)
goto error;
goto error;
if (fflush(fp) != 0)
goto error;
goto error;
if ((errno = ipc_response(fp, res, rlen)) != 0)
goto error;
goto error;
if ((errno = benc_validate(*res, *rlen)) != 0)
goto error;
goto error;

fclose(fp);
return 0;
@@ -142,14 +142,14 @@ btpd_die(struct ipc *ipc)
uint32_t rsiz;

if ((error = ipc_req_res(ipc, shutdown, size, &response, &rsiz)) != 0)
return error;
return error;

error = benc_validate(response, rsiz);

if (error == 0) {
int64_t tmp;
int64_t tmp;
benc_dget_int64(response, "code", &tmp);
error = tmp;
error = tmp;
}

free(response);
@@ -172,12 +172,12 @@ btpd_add(struct ipc *ipc, char **paths, unsigned npaths, char **out)
buf_write(&iob, paths[i], plen);
}
buf_print(&iob, "e");
error = ipc_req_res(ipc, iob.buf, iob.buf_off, &res, &reslen);
free(iob.buf);
if (error == 0)
*out = res;
*out = res;
return error;
}

@@ -210,11 +210,11 @@ btpd_del(struct ipc *ipc, uint8_t (*hash)[20], unsigned nhashes, char **out)
buf_write(&iob, hash[i], 20);
}
buf_write(&iob, "e", 1);
error = ipc_req_res(ipc, iob.buf, iob.buf_off, &res, &reslen);
free(iob.buf);
if (error != 0)
return error;
return error;

*out = res;
return 0;


+ 1
- 1
cli/btpd_if.h 파일 보기

@@ -14,7 +14,7 @@ int ipc_close(struct ipc *ipc);

int btpd_add(struct ipc *ipc, char **path, unsigned npaths, char **out);
int btpd_del(struct ipc *ipc, uint8_t (*hash)[20],
unsigned nhashes, char **out);
unsigned nhashes, char **out);
int btpd_die(struct ipc *ipc);
int btpd_stat(struct ipc *ipc, char **out);



+ 105
- 105
misc/benc.c 파일 보기

@@ -17,7 +17,7 @@ benc_validate(const char *p, size_t len)
const char *end = p + len - 1;

if (len <= 0)
return EINVAL;
return EINVAL;

return benc_validate_aux(p, end) == end ? 0 : EINVAL;
}
@@ -28,51 +28,51 @@ benc_validate_aux(const char *p, const char *end)
size_t d = 0;
switch (*p) {
case 'd':
d = 1;
d = 1;
case 'l':
for (p++; p <= end && *p != 'e'; p++) {
if (d != 0) {
if (d % 2 == 1 && !isdigit(*p))
return NULL;
else
d++;
}
if ((p = benc_validate_aux(p, end)) == NULL)
return NULL;
}
if (p > end || (d != 0 && d % 2 != 1))
return NULL;
break;
for (p++; p <= end && *p != 'e'; p++) {
if (d != 0) {
if (d % 2 == 1 && !isdigit(*p))
return NULL;
else
d++;
}
if ((p = benc_validate_aux(p, end)) == NULL)
return NULL;
}
if (p > end || (d != 0 && d % 2 != 1))
return NULL;
break;
case 'i':
p++;
if (p > end)
return NULL;
if (*p == '-')
p++;
if (p > end || !isdigit(*p))
return NULL;
p++;
while (p <= end && isdigit(*p))
p++;
if (p > end || *p != 'e')
return NULL;
break;
p++;
if (p > end)
return NULL;
if (*p == '-')
p++;
if (p > end || !isdigit(*p))
return NULL;
p++;
while (p <= end && isdigit(*p))
p++;
if (p > end || *p != 'e')
return NULL;
break;
default:
if (isdigit(*p)) {
size_t len = 0;
while (p <= end && isdigit(*p)) {
len *= 10;
len += *p - '0';
p++;
}
if (p <= end && *p == ':' && p + len <= end)
p += len;
else
return NULL;
}
else
return NULL;
break;
if (isdigit(*p)) {
size_t len = 0;
while (p <= end && isdigit(*p)) {
len *= 10;
len += *p - '0';
p++;
}
if (p <= end && *p == ':' && p + len <= end)
p += len;
else
return NULL;
}
else
return NULL;
break;
}
return p;
}
@@ -86,21 +86,21 @@ benc_length(const char *p)
switch (*p) {
case 'd':
case 'l':
blen = 2; // [l|d]...e
next = benc_first(p);
while (*next != 'e') {
size_t len = benc_length(next);
blen += len;
next += len;
}
return blen;
blen = 2; // [l|d]...e
next = benc_first(p);
while (*next != 'e') {
size_t len = benc_length(next);
blen += len;
next += len;
}
return blen;
case 'i':
for (next = p + 1; *next != 'e'; next++)
;
return next - p + 1;
for (next = p + 1; *next != 'e'; next++)
;
return next - p + 1;
default:
assert(benc_str(p, &next, &blen, NULL) == 0);
return next - p + blen;
assert(benc_str(p, &next, &blen, NULL) == 0);
return next - p + blen;
}
}

@@ -109,7 +109,7 @@ benc_nelems(const char *p)
{
size_t nelems = 0;
for (p = benc_first(p); p != NULL; p = benc_next(p))
nelems++;
nelems++;
return nelems;
}

@@ -135,9 +135,9 @@ benc_str(const char *p, const char **out, size_t *len, const char**next)
blen = *p - '0';
p++;
while (isdigit(*p)) {
blen *= 10;
blen += *p - '0';
p++;
blen *= 10;
blen += *p - '0';
p++;
}
assert(*p == ':');
benc_safeset(len, blen);
@@ -154,12 +154,12 @@ benc_strz(const char *p, char **out, size_t *len, const char **next)
const char *bstr;

if ((err = benc_str(p, &bstr, &blen, next)) == 0) {
if ((*out = malloc(blen + 1)) != NULL) {
memcpy(*out, bstr, blen);
(*out)[blen] = '\0';
benc_safeset(len, blen);
} else
err = ENOMEM;
if ((*out = malloc(blen + 1)) != NULL) {
memcpy(*out, bstr, blen);
(*out)[blen] = '\0';
benc_safeset(len, blen);
} else
err = ENOMEM;
}
return err;
}
@@ -172,11 +172,11 @@ benc_stra(const char *p, char **out, size_t *len, const char **next)
const char *bstr;

if ((err = benc_str(p, &bstr, &blen, next)) == 0) {
if ((*out = malloc(blen)) != NULL) {
memcpy(*out, bstr, blen);
benc_safeset(len, blen);
} else
err = ENOMEM;
if ((*out = malloc(blen)) != NULL) {
memcpy(*out, bstr, blen);
benc_safeset(len, blen);
} else
err = ENOMEM;
}
return err;
}
@@ -190,16 +190,16 @@ benc_int64(const char *p, int64_t *out, const char **next)
assert(*p == 'i');
p++;
if (*p == '-') {
sign = -1;
p++;
sign = -1;
p++;
}
assert(isdigit(*p));
res += sign * (*p - '0');
p++;
while (isdigit(*p)) {
res *= sign * 10;
res += sign * (*p - '0');
p++;
res *= sign * 10;
res += sign * (*p - '0');
p++;
}
assert(*p == 'e');
benc_safeset(out, res);
@@ -214,10 +214,10 @@ benc_uint32(const char *p, uint32_t *out, const char **next)
int err;
int64_t res;
if ((err = benc_int64(p, &res, next)) == 0) {
if (res >= 0 && res <= 0xffffffffUL)
*out = (uint32_t)res;
else
err = EINVAL;
if (res >= 0 && res <= 0xffffffffUL)
*out = (uint32_t)res;
else
err = EINVAL;
}
return err;
}
@@ -235,17 +235,17 @@ benc_dget_any(const char *p, const char *key, const char **val)

p = benc_first(p);
while (p != NULL) {
if ((res = benc_str(p, &bstr, &blen, &p)) != 0)
return res;
res = strncmp(bstr, key, blen);
if (res == 0 && len == blen) {
*val = p;
return 0;
} else if (res <= 0) {
p = benc_next(p);
} else
return ENOENT;
if ((res = benc_str(p, &bstr, &blen, &p)) != 0)
return res;
res = strncmp(bstr, key, blen);
if (res == 0 && len == blen) {
*val = p;
return 0;
} else if (res <= 0) {
p = benc_next(p);
} else
return ENOENT;
}
return ENOENT;
}
@@ -255,8 +255,8 @@ benc_dget_lst(const char *p, const char *key, const char **val)
{
int err;
if ((err = benc_dget_any(p, key, val)) == 0)
if (!benc_islst(*val))
err = EINVAL;
if (!benc_islst(*val))
err = EINVAL;
return err;
}

@@ -265,8 +265,8 @@ benc_dget_dct(const char *p, const char *key, const char **val)
{
int err;
if ((err = benc_dget_any(p, key, val)) == 0)
if (!benc_isdct(*val))
err = EINVAL;
if (!benc_isdct(*val))
err = EINVAL;
return err;
}

@@ -276,8 +276,8 @@ benc_dget_str(const char *p, const char *key, const char **val, size_t *len)
int err;
const char *sp;
if ((err = benc_dget_any(p, key, &sp)) == 0)
err = benc_isstr(sp) ? benc_str(sp, val, len, NULL) : EINVAL;
return err;
err = benc_isstr(sp) ? benc_str(sp, val, len, NULL) : EINVAL;
return err;
}

int
@@ -286,8 +286,8 @@ benc_dget_stra(const char *p, const char *key, char **val, size_t *len)
int err;
const char *sp;
if ((err = benc_dget_any(p, key, &sp)) == 0)
err = benc_isstr(sp) ? benc_stra(sp, val, len, NULL) : EINVAL;
return err;
err = benc_isstr(sp) ? benc_stra(sp, val, len, NULL) : EINVAL;
return err;
}

int
@@ -296,8 +296,8 @@ benc_dget_strz(const char *p, const char *key, char **val, size_t *len)
int err;
const char *sp;
if ((err = benc_dget_any(p, key, &sp)) == 0)
err = benc_isstr(sp) ? benc_strz(sp, val, len, NULL) : EINVAL;
return err;
err = benc_isstr(sp) ? benc_strz(sp, val, len, NULL) : EINVAL;
return err;
}

int
@@ -306,9 +306,9 @@ benc_dget_int64(const char *p, const char *key, int64_t *val)
int err;
const char *ip;
if ((err = benc_dget_any(p, key, &ip)) == 0)
err = benc_isint(ip) ? benc_int64(ip, val, NULL) : EINVAL;
err = benc_isint(ip) ? benc_int64(ip, val, NULL) : EINVAL;
return err;
}
}

int
benc_dget_uint32(const char *p, const char *key, uint32_t *val)
@@ -316,9 +316,9 @@ benc_dget_uint32(const char *p, const char *key, uint32_t *val)
int err;
const char *ip;
if ((err = benc_dget_any(p, key, &ip)) == 0)
err = benc_isint(ip) ? benc_uint32(ip, val, NULL) : EINVAL;
err = benc_isint(ip) ? benc_uint32(ip, val, NULL) : EINVAL;
return err;
}
}

int
benc_islst(const char *p)


+ 1
- 1
misc/benc.h 파일 보기

@@ -21,7 +21,7 @@ int benc_dget_any(const char *p, const char *key, const char **val);
int benc_dget_lst(const char *p, const char *key, const char **val);
int benc_dget_dct(const char *p, const char *key, const char **val);
int benc_dget_str(const char *p, const char *key,
const char **val, size_t *len);
const char **val, size_t *len);
int benc_dget_stra(const char *p, const char *key, char **val, size_t *len);
int benc_dget_strz(const char *p, const char *key, char **val, size_t *len);
int benc_dget_int64(const char *p, const char *key, int64_t *val);


+ 100
- 100
misc/metainfo.c 파일 보기

@@ -44,7 +44,7 @@ print_metainfo(struct metainfo *tp)

printf("Info hash: ");
for (i = 0; i < 20; i++)
printf("%.2x", tp->info_hash[i]);
printf("%.2x", tp->info_hash[i]);
printf("\n");
printf("Tracker URL: %s\n", tp->announce);
printf("Piece length: %" PRId64 "\n", (int64_t)tp->piece_length);
@@ -53,8 +53,8 @@ print_metainfo(struct metainfo *tp)
printf("Advisory name: %s\n", tp->name);
printf("Files:\n");
for (i = 0; i < tp->nfiles; i++) {
printf("%s (%" PRId64 ")\n",
tp->files[i].path, (int64_t)tp->files[i].length);
printf("%s (%" PRId64 ")\n",
tp->files[i].path, (int64_t)tp->files[i].length);
}
printf("Total length: %" PRId64 "\n\n", (int64_t)tp->total_length);
}
@@ -63,13 +63,13 @@ static int
check_path(const char *path, size_t len)
{
if (len == 0)
return 0;
return 0;
else if (len == 1 && path[0] == '.')
return 0;
return 0;
else if (len == 2 && path[0] == '.' && path[1] == '.')
return 0;
return 0;
else if (memchr(path, '/', len) != NULL)
return 0;
return 0;
return 1;
}

@@ -81,27 +81,27 @@ fill_fileinfo(const char *fdct, struct fileinfo *tfp)
const char *plst, *iter, *str;

if ((err = benc_dget_off(fdct, "length", &tfp->length)) != 0)
return err;
return err;

if ((err = benc_dget_lst(fdct, "path", &plst)) != 0)
return err;
return err;

npath = plen = 0;
iter = benc_first(plst);
while (iter != NULL) {
if (!benc_isstr(iter))
return EINVAL;
benc_str(iter, &str, &len, &iter);
if (!check_path(str, len))
return EINVAL;
npath++;
plen += len;
if (!benc_isstr(iter))
return EINVAL;
benc_str(iter, &str, &len, &iter);
if (!check_path(str, len))
return EINVAL;
npath++;
plen += len;
}
if (npath == 0)
return EINVAL;
return EINVAL;

if ((tfp->path = malloc(plen + (npath - 1) + 1)) == NULL)
return ENOMEM;
return ENOMEM;

iter = benc_first(plst);
benc_str(iter, &str, &len, &iter);
@@ -109,11 +109,11 @@ fill_fileinfo(const char *fdct, struct fileinfo *tfp)
plen = len;
npath--;
while (npath > 0) {
tfp->path[plen++] = '/';
benc_str(iter, &str, &len, &iter);
memcpy(tfp->path + plen, str, len);
plen += len;
npath--;
tfp->path[plen++] = '/';
benc_str(iter, &str, &len, &iter);
memcpy(tfp->path + plen, str, len);
plen += len;
npath--;
}
tfp->path[plen] = '\0';
return 0;
@@ -124,18 +124,18 @@ clear_metainfo(struct metainfo *mip)
{
int i;
if (mip->piece_hash != NULL)
free(mip->piece_hash);
free(mip->piece_hash);
if (mip->announce != NULL)
free(mip->announce);
free(mip->announce);
if (mip->files != NULL) {
for (i = 0; i < mip->nfiles; i++) {
if (mip->files[i].path != NULL)
free(mip->files[i].path);
}
free(mip->files);
for (i = 0; i < mip->nfiles; i++) {
if (mip->files[i].path != NULL)
free(mip->files[i].path);
}
free(mip->files);
}
if (mip->name != NULL)
free(mip->name);
free(mip->name);
}

int
@@ -147,91 +147,91 @@ fill_metainfo(const char *bep, struct metainfo *tp, int mem_hashes)
const char *hash_addr;

if (!benc_isdct(bep))
return EINVAL;
return EINVAL;

if ((err = benc_dget_strz(bep, "announce", &tp->announce, NULL)) != 0)
goto out;
goto out;

if ((err = benc_dget_dct(bep, "info", &bep)) != 0)
goto out;
goto out;

SHA1(bep, benc_length(bep), tp->info_hash);

if ((err = benc_dget_off(bep, "piece length", &tp->piece_length)) != 0)
goto out;
goto out;

if ((err = benc_dget_str(bep, "pieces", &hash_addr, &len)) != 0)
goto out;
goto out;

if (len % 20 != 0) {
err = EINVAL;
goto out;
err = EINVAL;
goto out;
}
tp->npieces = len / 20;

tp->pieces_off = hash_addr - base_addr;
if (mem_hashes) {
if ((tp->piece_hash = malloc(len)) == NULL) {
err = ENOMEM;
goto out;
}
bcopy(hash_addr, tp->piece_hash, len);
if ((tp->piece_hash = malloc(len)) == NULL) {
err = ENOMEM;
goto out;
}
bcopy(hash_addr, tp->piece_hash, len);
}

if ((err = benc_dget_strz(bep, "name", &tp->name, NULL)) != 0)
goto out;
goto out;

err = benc_dget_off(bep, "length", &tp->total_length);
if (err == 0) {
tp->nfiles = 1;
tp->files = calloc(1, sizeof(struct fileinfo));
if (tp->files != NULL) {
tp->files[0].length = tp->total_length;
tp->files[0].path = strdup(tp->name);
if (tp->files[0].path == NULL) {
err = ENOMEM;
goto out;
}
} else {
err = ENOMEM;
goto out;
}
tp->nfiles = 1;
tp->files = calloc(1, sizeof(struct fileinfo));
if (tp->files != NULL) {
tp->files[0].length = tp->total_length;
tp->files[0].path = strdup(tp->name);
if (tp->files[0].path == NULL) {
err = ENOMEM;
goto out;
}
} else {
err = ENOMEM;
goto out;
}
}
else if (err == ENOENT) {
int i;
const char *flst, *fdct;
if ((err = benc_dget_lst(bep, "files", &flst)) != 0)
goto out;
tp->nfiles = benc_nelems(flst);
if (tp->nfiles < 1) {
err = EINVAL;
goto out;
}
tp->files = calloc(tp->nfiles, sizeof(struct fileinfo));
tp->total_length = 0;
i = 0;
for (fdct = benc_first(flst); fdct != NULL; fdct = benc_next(fdct)) {
if (!benc_isdct(fdct)) {
err = EINVAL;
goto out;
}
if ((err = fill_fileinfo(fdct, &tp->files[i])) != 0)
goto out;
tp->total_length += tp->files[i].length;
i++;
}
int i;
const char *flst, *fdct;
if ((err = benc_dget_lst(bep, "files", &flst)) != 0)
goto out;
tp->nfiles = benc_nelems(flst);
if (tp->nfiles < 1) {
err = EINVAL;
goto out;
}
tp->files = calloc(tp->nfiles, sizeof(struct fileinfo));
tp->total_length = 0;
i = 0;
for (fdct = benc_first(flst); fdct != NULL; fdct = benc_next(fdct)) {
if (!benc_isdct(fdct)) {
err = EINVAL;
goto out;
}
if ((err = fill_fileinfo(fdct, &tp->files[i])) != 0)
goto out;
tp->total_length += tp->files[i].length;
i++;
}
}
else
goto out;
goto out;
out:
if (err != 0)
clear_metainfo(tp);
clear_metainfo(tp);

return err;
}
@@ -244,31 +244,31 @@ load_metainfo(const char *path, off_t size, int mem_hashes,
int fd, err = 0;

if ((fd = open(path, O_RDONLY)) == -1)
return errno;
return errno;

if (size <= 0) {
struct stat sb;
if (fstat(fd, &sb) == -1) {
close(fd);
return errno;
} else
size = sb.st_size;
struct stat sb;
if (fstat(fd, &sb) == -1) {
close(fd);
return errno;
} else
size = sb.st_size;
}

if ((buf = mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED)
err = errno;
err = errno;
close(fd);

if (err == 0)
err = benc_validate(buf, size);
err = benc_validate(buf, size);

if (err == 0)
if ((*res = calloc(1, sizeof(**res))) == NULL)
err = ENOMEM;
if ((*res = calloc(1, sizeof(**res))) == NULL)
err = ENOMEM;

if (err == 0)
if ((err = fill_metainfo(buf, *res, mem_hashes)) != 0)
free(*res);
if ((err = fill_metainfo(buf, *res, mem_hashes)) != 0)
free(*res);

munmap(buf, size);
return err;


+ 80
- 80
misc/stream.c 파일 보기

@@ -16,7 +16,7 @@ bts_open_ro(struct metainfo *meta, off_t off, F_fdcb fd_cb, void *fd_arg)
{
struct bt_stream_ro *bts = malloc(sizeof(*bts));
if (bts == NULL)
return NULL;
return NULL;

bts->meta = meta;
bts->fd_cb = fd_cb;
@@ -37,16 +37,16 @@ bts_seek_ro(struct bt_stream_ro *bts, off_t off)
assert(off >= 0 && off <= bts->meta->total_length);

if (bts->fd != -1) {
close(bts->fd);
bts->fd = -1;
close(bts->fd);
bts->fd = -1;
}

bts->t_off = off;
bts->index = 0;

while (off >= files[bts->index].length) {
off -= files[bts->index].length;
bts->index++;
off -= files[bts->index].length;
bts->index++;
}

bts->f_off = off;
@@ -63,31 +63,31 @@ bts_read_ro(struct bt_stream_ro *bts, char *buf, size_t len)

boff = 0;
while (boff < len) {
if (bts->fd == -1) {
int err =
bts->fd_cb(files[bts->index].path, &bts->fd, bts->fd_arg);
if (err != 0)
return err;
if (bts->f_off != 0)
lseek(bts->fd, bts->f_off, SEEK_SET);
}
wantread = min(len - boff, files[bts->index].length - bts->f_off);
didread = read(bts->fd, buf + boff, wantread);
if (didread == -1)
return errno;
boff += didread;
bts->f_off += didread;
bts->t_off += didread;
if (bts->f_off == files[bts->index].length) {
close(bts->fd);
bts->fd = -1;
bts->f_off = 0;
bts->index++;
}
if (didread != wantread)
return ENOENT;
if (bts->fd == -1) {
int err =
bts->fd_cb(files[bts->index].path, &bts->fd, bts->fd_arg);
if (err != 0)
return err;
if (bts->f_off != 0)
lseek(bts->fd, bts->f_off, SEEK_SET);
}
wantread = min(len - boff, files[bts->index].length - bts->f_off);
didread = read(bts->fd, buf + boff, wantread);
if (didread == -1)
return errno;
boff += didread;
bts->f_off += didread;
bts->t_off += didread;
if (bts->f_off == files[bts->index].length) {
close(bts->fd);
bts->fd = -1;
bts->f_off = 0;
bts->index++;
}
if (didread != wantread)
return ENOENT;
}
return 0;
}
@@ -96,7 +96,7 @@ void
bts_close_ro(struct bt_stream_ro *bts)
{
if (bts->fd != -1)
close(bts->fd);
close(bts->fd);
free(bts);
}

@@ -112,11 +112,11 @@ bts_sha(struct bt_stream_ro *bts, off_t length, uint8_t *hash)

SHA1_Init(&ctx);
while (length > 0) {
wantread = min(length, SHAFILEBUF);
if ((err = bts_read_ro(bts, buf, wantread)) != 0)
break;
length -= wantread;
SHA1_Update(&ctx, buf, wantread);
wantread = min(length, SHAFILEBUF);
if ((err = bts_read_ro(bts, buf, wantread)) != 0)
break;
length -= wantread;
SHA1_Update(&ctx, buf, wantread);
}
SHA1_Final(hash, &ctx);
return err;
@@ -136,23 +136,23 @@ bts_hashes(struct metainfo *meta,
off_t llen = meta->total_length % plen;

if ((bts = bts_open_ro(meta, 0, fd_cb, arg)) == NULL)
return ENOMEM;
for (piece = 0; piece < meta->npieces; piece++) {
return ENOMEM;
for (piece = 0; piece < meta->npieces; piece++) {
if (piece < meta->npieces - 1)
err = bts_sha(bts, plen, hash);
else
err = bts_sha(bts, llen, hash);
if (err == 0)
cb(piece, hash, arg);
else if (err == ENOENT) {
cb(piece, NULL, arg);
if (piece < meta->npieces - 1)
bts_seek_ro(bts, (piece + 1) * plen);
err = 0;
} else
break;
err = bts_sha(bts, plen, hash);
else
err = bts_sha(bts, llen, hash);
if (err == 0)
cb(piece, hash, arg);
else if (err == ENOENT) {
cb(piece, NULL, arg);
if (piece < meta->npieces - 1)
bts_seek_ro(bts, (piece + 1) * plen);
err = 0;
} else
break;
}
bts_close_ro(bts);
return err;
@@ -163,7 +163,7 @@ bts_open_wo(struct metainfo *meta, off_t off, F_fdcb fd_cb, void *fd_arg)
{
struct bt_stream_wo *bts = malloc(sizeof(*bts));
if (bts == NULL)
return NULL;
return NULL;

bts->meta = meta;
bts->fd_cb = fd_cb;
@@ -187,24 +187,24 @@ bts_write_wo(struct bt_stream_wo *bts, const char *buf, size_t len)

boff = 0;
while (boff < len) {
if (bts->fd == -1) {
int err =
bts->fd_cb(files[bts->index].path, &bts->fd, bts->fd_arg);
if (err != 0)
return err;
if (bts->f_off != 0)
lseek(bts->fd, bts->f_off, SEEK_SET);
}
wantwrite = min(len - boff, files[bts->index].length - bts->f_off);
didwrite = write(bts->fd, buf + boff, wantwrite);
if (didwrite == -1)
return errno;
boff += didwrite;
bts->f_off += didwrite;
bts->t_off += didwrite;
if (bts->f_off == files[bts->index].length) {
if (bts->fd == -1) {
int err =
bts->fd_cb(files[bts->index].path, &bts->fd, bts->fd_arg);
if (err != 0)
return err;
if (bts->f_off != 0)
lseek(bts->fd, bts->f_off, SEEK_SET);
}
wantwrite = min(len - boff, files[bts->index].length - bts->f_off);
didwrite = write(bts->fd, buf + boff, wantwrite);
if (didwrite == -1)
return errno;
boff += didwrite;
bts->f_off += didwrite;
bts->t_off += didwrite;
if (bts->f_off == files[bts->index].length) {
if (fsync(bts->fd) == -1) {
int err = errno;
close(bts->fd);
@@ -212,10 +212,10 @@ bts_write_wo(struct bt_stream_wo *bts, const char *buf, size_t len)
}
if (close(bts->fd) == -1)
return errno;
bts->fd = -1;
bts->f_off = 0;
bts->index++;
}
bts->fd = -1;
bts->f_off = 0;
bts->index++;
}
}
return 0;
}
@@ -225,11 +225,11 @@ bts_close_wo(struct bt_stream_wo *bts)
{
int err = 0;
if (bts->fd != -1) {
if (fsync(bts->fd) == -1) {
err = errno;
close(bts->fd);
} else if (close(bts->fd) == -1)
err = errno;
if (fsync(bts->fd) == -1) {
err = errno;
close(bts->fd);
} else if (close(bts->fd) == -1)
err = errno;
}
free(bts);
return err;


+ 1
- 1
misc/stream.h 파일 보기

@@ -31,6 +31,6 @@ int bts_close_wo(struct bt_stream_wo *bts);

int bts_sha(struct bt_stream_ro *bts, off_t length, uint8_t *hash);
int bts_hashes(struct metainfo *, F_fdcb fd_cb,
void (*cb)(uint32_t, uint8_t *, void *), void *arg);
void (*cb)(uint32_t, uint8_t *, void *), void *arg);

#endif

+ 35
- 35
misc/subr.c 파일 보기

@@ -34,9 +34,9 @@ set_nonblocking(int fd)
{
int oflags;
if ((oflags = fcntl(fd, F_GETFL, 0)) == -1)
return errno;
return errno;
if (fcntl(fd, F_SETFL, oflags | O_NONBLOCK) == -1)
return errno;
return errno;
return 0;
}

@@ -45,9 +45,9 @@ set_blocking(int fd)
{
int oflags;
if ((oflags = fcntl(fd, F_GETFL, 0)) == -1)
return errno;
return errno;
if (fcntl(fd, F_SETFL, oflags & ~O_NONBLOCK) == -1)
return errno;
return errno;
return 0;
}

@@ -58,16 +58,16 @@ mkdirs(char *path)
char *spos = strchr(path + 1, '/'); // Must ignore the root

while (spos != NULL) {
*spos = '\0';
err = mkdir(path, 0777);
*spos = '/';
if (err != 0 && errno != EEXIST) {
err = errno;
break;
}
spos = strchr(spos + 1, '/');
*spos = '\0';
err = mkdir(path, 0777);
*spos = '/';
if (err != 0 && errno != EEXIST) {
err = errno;
break;
}
spos = strchr(spos + 1, '/');
}
return err;
}
@@ -81,8 +81,8 @@ vopen(int *res, int flags, const char *fmt, ...)

va_start(ap, fmt);
if (vsnprintf(path, PATH_MAX, fmt, ap) >= PATH_MAX) {
va_end(ap);
return ENAMETOOLONG;
va_end(ap);
return ENAMETOOLONG;
}
va_end(ap);

@@ -90,18 +90,18 @@ vopen(int *res, int flags, const char *fmt, ...)
again:
fd = open(path, flags, 0666);
if (fd < 0 && errno == ENOENT && (flags & O_CREAT) != 0 && !didmkdirs) {
if (mkdirs(path) == 0) {
didmkdirs = 1;
goto again;
} else
return errno;
if (mkdirs(path) == 0) {
didmkdirs = 1;
goto again;
} else
return errno;
}

if (fd >= 0) {
*res = fd;
return 0;
*res = fd;
return 0;
} else
return errno;
return errno;
}

int
@@ -110,22 +110,22 @@ canon_path(const char *path, char **res)
char rp[PATH_MAX];

if (realpath(path, rp) == NULL)
return errno;
return errno;
#if 0
// This could be necessary on solaris.
if (rp[0] != '/') {
char wd[MAXPATHLEN];
if (getcwd(wd, MAXPATHLEN) == NULL)
return errno;
if (strlcat(wd, "/", MAXPATHLEN) >= MAXPATHLEN)
return ENAMETOOLONG;
if (strlcat(wd, rp, MAXPATHLEN) >= MAXPATHLEN)
return ENAMETOOLONG;
strcpy(rp, wd);
char wd[MAXPATHLEN];
if (getcwd(wd, MAXPATHLEN) == NULL)
return errno;
if (strlcat(wd, "/", MAXPATHLEN) >= MAXPATHLEN)
return ENAMETOOLONG;
if (strlcat(wd, rp, MAXPATHLEN) >= MAXPATHLEN)
return ENAMETOOLONG;
strcpy(rp, wd);
}
#endif
if ((*res = strdup(rp)) == NULL)
return ENOMEM;
return ENOMEM;

return 0;
}
@@ -136,6 +136,6 @@ round_to_page(size_t size)
size_t psize = getpagesize();
size_t rem = size % psize;
if (rem != 0)
size += psize - rem;
size += psize - rem;
return size;
}

불러오는 중...
취소
저장