@@ -315,3 +315,33 @@ peer_on_cancel(struct peer *p, uint32_t index, uint32_t begin, | |||||
req = BTPDQ_NEXT(req, entry); | req = BTPDQ_NEXT(req, entry); | ||||
} | } | ||||
} | } | ||||
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; | |||||
} |
@@ -78,4 +78,10 @@ void peer_on_request(struct peer *p, uint32_t index, uint32_t begin, | |||||
void peer_on_cancel(struct peer *p, uint32_t index, uint32_t begin, | void peer_on_cancel(struct peer *p, uint32_t index, uint32_t begin, | ||||
uint32_t length); | uint32_t length); | ||||
int peer_chokes(struct peer *p); | |||||
int peer_wanted(struct peer *p); | |||||
int peer_laden(struct peer *p); | |||||
int peer_has(struct peer *p, uint32_t index); | |||||
int peer_leech_ok(struct peer *p); | |||||
#endif | #endif |
@@ -8,25 +8,18 @@ void next_optimistic(struct torrent *tp, struct peer *np); | |||||
// policy_subr.c | // policy_subr.c | ||||
struct piece *torrent_get_piece(struct torrent *tp, uint32_t index); | |||||
int piece_full(struct piece *pc); | int piece_full(struct piece *pc); | ||||
int peer_chokes(struct peer *p); | |||||
int peer_wanted(struct peer *p); | |||||
int peer_laden(struct peer *p); | |||||
int peer_has(struct peer *p, uint32_t index); | |||||
int peer_leech_ok(struct peer *p); | |||||
void piece_free(struct piece *pc); | void piece_free(struct piece *pc); | ||||
void cm_on_piece_unfull(struct piece *pc); | void cm_on_piece_unfull(struct piece *pc); | ||||
void cm_on_piece(struct piece *pc); | void cm_on_piece(struct piece *pc); | ||||
struct piece *cm_new_piece(struct torrent *tp, uint32_t index); | struct piece *cm_new_piece(struct torrent *tp, uint32_t index); | ||||
struct piece *cm_find_piece(struct torrent *tp, uint32_t index); | |||||
unsigned cm_piece_assign_requests(struct piece *pc, struct peer *p); | unsigned cm_piece_assign_requests(struct piece *pc, struct peer *p); | ||||
void cm_piece_assign_requests_eg(struct piece *pc, struct peer *p); | void cm_piece_assign_requests_eg(struct piece *pc, struct peer *p); | ||||
unsigned cm_assign_requests(struct peer *p); | unsigned cm_assign_requests(struct peer *p); | ||||
void cm_assign_requests_eg(struct peer *p); | void cm_assign_requests_eg(struct peer *p); | ||||
void cm_unassign_requests(struct peer *p); | void cm_unassign_requests(struct peer *p); | ||||
void cm_unassign_requests_eg(struct peer *p); | void cm_unassign_requests_eg(struct peer *p); | ||||
@@ -30,7 +30,7 @@ cm_on_piece_ann(struct peer *p, uint32_t index) | |||||
tp->piece_count[index]++; | tp->piece_count[index]++; | ||||
if (has_bit(tp->piece_field, index)) | if (has_bit(tp->piece_field, index)) | ||||
return; | return; | ||||
struct piece *pc = torrent_get_piece(tp, index); | |||||
struct piece *pc = cm_find_piece(tp, index); | |||||
if (tp->endgame) { | if (tp->endgame) { | ||||
if (pc != NULL) { | if (pc != NULL) { | ||||
peer_want(p, index); | peer_want(p, index); | ||||
@@ -241,7 +241,7 @@ cm_on_block(struct peer *p, uint32_t index, uint32_t begin, uint32_t length, | |||||
off_t cbegin = index * p->tp->meta.piece_length + begin; | off_t cbegin = index * p->tp->meta.piece_length + begin; | ||||
torrent_put_bytes(p->tp, data, cbegin, length); | torrent_put_bytes(p->tp, data, cbegin, length); | ||||
struct piece *pc = torrent_get_piece(tp, index); | |||||
struct piece *pc = cm_find_piece(tp, index); | |||||
assert(pc != NULL); | assert(pc != NULL); | ||||
uint32_t block = begin / PIECE_BLOCKLEN; | uint32_t block = begin / PIECE_BLOCKLEN; | ||||
@@ -29,6 +29,56 @@ | |||||
#include "btpd.h" | #include "btpd.h" | ||||
#include "stream.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 | static int | ||||
cm_should_enter_endgame(struct torrent *tp) | 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 * | struct piece * | ||||
torrent_get_piece(struct torrent *tp, uint32_t index) | |||||
cm_find_piece(struct torrent *tp, uint32_t index) | |||||
{ | { | ||||
struct piece *pc; | struct piece *pc; | ||||
BTPDQ_FOREACH(pc, &tp->getlst, entry) | BTPDQ_FOREACH(pc, &tp->getlst, entry) | ||||
@@ -117,50 +131,6 @@ torrent_get_piece(struct torrent *tp, uint32_t index) | |||||
return pc; | 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 | static int | ||||
test_hash(struct torrent *tp, uint8_t *hash, unsigned long index) | test_hash(struct torrent *tp, uint8_t *hash, unsigned long index) | ||||
{ | { | ||||