|
|
@@ -29,6 +29,56 @@ |
|
|
|
#include "btpd.h" |
|
|
|
#include "stream.h" |
|
|
|
|
|
|
|
static struct piece * |
|
|
|
piece_alloc(struct torrent *tp, uint32_t index) |
|
|
|
{ |
|
|
|
assert(!has_bit(tp->busy_field, index) |
|
|
|
&& tp->npcs_busy < tp->meta.npieces); |
|
|
|
struct piece *pc; |
|
|
|
size_t mem, field; |
|
|
|
unsigned nblocks; |
|
|
|
off_t piece_length = torrent_piece_size(tp, index); |
|
|
|
|
|
|
|
nblocks = (unsigned)ceil((double)piece_length / PIECE_BLOCKLEN); |
|
|
|
field = (size_t)ceil(nblocks / 8.0); |
|
|
|
mem = sizeof(*pc) + field; |
|
|
|
|
|
|
|
pc = btpd_calloc(1, mem); |
|
|
|
pc->tp = tp; |
|
|
|
pc->down_field = (uint8_t *)(pc + 1); |
|
|
|
pc->have_field = |
|
|
|
tp->block_field + |
|
|
|
(size_t)ceil(index * tp->meta.piece_length / (double)(1 << 17)); |
|
|
|
pc->nblocks = nblocks; |
|
|
|
pc->index = index; |
|
|
|
|
|
|
|
for (unsigned i = 0; i < nblocks; i++) |
|
|
|
if (has_bit(pc->have_field, i)) |
|
|
|
pc->ngot++; |
|
|
|
|
|
|
|
tp->npcs_busy++; |
|
|
|
set_bit(tp->busy_field, index); |
|
|
|
BTPDQ_INSERT_HEAD(&tp->getlst, pc, entry); |
|
|
|
return pc; |
|
|
|
} |
|
|
|
|
|
|
|
void |
|
|
|
piece_free(struct piece *pc) |
|
|
|
{ |
|
|
|
struct torrent *tp = pc->tp; |
|
|
|
assert(tp->npcs_busy > 0); |
|
|
|
tp->npcs_busy--; |
|
|
|
clear_bit(tp->busy_field, pc->index); |
|
|
|
BTPDQ_REMOVE(&pc->tp->getlst, pc, entry); |
|
|
|
free(pc); |
|
|
|
} |
|
|
|
|
|
|
|
int |
|
|
|
piece_full(struct piece *pc) |
|
|
|
{ |
|
|
|
return pc->ngot + pc->nbusy == pc->nblocks; |
|
|
|
} |
|
|
|
|
|
|
|
static int |
|
|
|
cm_should_enter_endgame(struct torrent *tp) |
|
|
|
{ |
|
|
@@ -71,44 +121,8 @@ cm_enter_endgame(struct torrent *tp) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
int |
|
|
|
peer_chokes(struct peer *p) |
|
|
|
{ |
|
|
|
return p->flags & PF_P_CHOKE; |
|
|
|
} |
|
|
|
|
|
|
|
int |
|
|
|
peer_has(struct peer *p, uint32_t index) |
|
|
|
{ |
|
|
|
return has_bit(p->piece_field, index); |
|
|
|
} |
|
|
|
|
|
|
|
int |
|
|
|
peer_laden(struct peer *p) |
|
|
|
{ |
|
|
|
return p->nreqs_out >= MAXPIPEDREQUESTS; |
|
|
|
} |
|
|
|
|
|
|
|
int |
|
|
|
peer_wanted(struct peer *p) |
|
|
|
{ |
|
|
|
return (p->flags & PF_I_WANT) == PF_I_WANT; |
|
|
|
} |
|
|
|
|
|
|
|
int |
|
|
|
peer_leech_ok(struct peer *p) |
|
|
|
{ |
|
|
|
return (p->flags & (PF_I_WANT|PF_P_CHOKE)) == PF_I_WANT; |
|
|
|
} |
|
|
|
|
|
|
|
int |
|
|
|
piece_full(struct piece *pc) |
|
|
|
{ |
|
|
|
return pc->ngot + pc->nbusy == pc->nblocks; |
|
|
|
} |
|
|
|
|
|
|
|
struct piece * |
|
|
|
torrent_get_piece(struct torrent *tp, uint32_t index) |
|
|
|
cm_find_piece(struct torrent *tp, uint32_t index) |
|
|
|
{ |
|
|
|
struct piece *pc; |
|
|
|
BTPDQ_FOREACH(pc, &tp->getlst, entry) |
|
|
@@ -117,50 +131,6 @@ torrent_get_piece(struct torrent *tp, uint32_t index) |
|
|
|
return pc; |
|
|
|
} |
|
|
|
|
|
|
|
static struct piece * |
|
|
|
piece_alloc(struct torrent *tp, uint32_t index) |
|
|
|
{ |
|
|
|
assert(!has_bit(tp->busy_field, index) |
|
|
|
&& tp->npcs_busy < tp->meta.npieces); |
|
|
|
struct piece *pc; |
|
|
|
size_t mem, field; |
|
|
|
unsigned nblocks; |
|
|
|
off_t piece_length = torrent_piece_size(tp, index); |
|
|
|
|
|
|
|
nblocks = (unsigned)ceil((double)piece_length / PIECE_BLOCKLEN); |
|
|
|
field = (size_t)ceil(nblocks / 8.0); |
|
|
|
mem = sizeof(*pc) + field; |
|
|
|
|
|
|
|
pc = btpd_calloc(1, mem); |
|
|
|
pc->tp = tp; |
|
|
|
pc->down_field = (uint8_t *)(pc + 1); |
|
|
|
pc->have_field = |
|
|
|
tp->block_field + |
|
|
|
(size_t)ceil(index * tp->meta.piece_length / (double)(1 << 17)); |
|
|
|
pc->nblocks = nblocks; |
|
|
|
pc->index = index; |
|
|
|
|
|
|
|
for (unsigned i = 0; i < nblocks; i++) |
|
|
|
if (has_bit(pc->have_field, i)) |
|
|
|
pc->ngot++; |
|
|
|
|
|
|
|
tp->npcs_busy++; |
|
|
|
set_bit(tp->busy_field, index); |
|
|
|
BTPDQ_INSERT_HEAD(&tp->getlst, pc, entry); |
|
|
|
return pc; |
|
|
|
} |
|
|
|
|
|
|
|
void |
|
|
|
piece_free(struct piece *pc) |
|
|
|
{ |
|
|
|
struct torrent *tp = pc->tp; |
|
|
|
assert(tp->npcs_busy > 0); |
|
|
|
tp->npcs_busy--; |
|
|
|
clear_bit(tp->busy_field, pc->index); |
|
|
|
BTPDQ_REMOVE(&pc->tp->getlst, pc, entry); |
|
|
|
free(pc); |
|
|
|
} |
|
|
|
|
|
|
|
static int |
|
|
|
test_hash(struct torrent *tp, uint8_t *hash, unsigned long index) |
|
|
|
{ |
|
|
|