Pārlūkot izejas kodu

* Move the network related parts of the torrent struct to a sub struct.

* Move some struct and type definitions to net_types.h
* Fix ul_on_lost_peer. I must've been very tired when I wrote it :P
master
Richard Nyberg pirms 19 gadiem
vecāks
revīzija
2d21101699
16 mainītis faili ar 310 papildinājumiem un 307 dzēšanām
  1. +1
    -1
      btpd/Makefile.am
  2. +1
    -0
      btpd/btpd.h
  3. +2
    -2
      btpd/content.c
  4. +28
    -47
      btpd/download.c
  5. +2
    -5
      btpd/download.h
  6. +57
    -57
      btpd/download_subr.c
  7. +66
    -32
      btpd/net.c
  8. +2
    -0
      btpd/net.h
  9. +114
    -0
      btpd/net_types.h
  10. +21
    -20
      btpd/peer.c
  11. +2
    -65
      btpd/peer.h
  12. +1
    -16
      btpd/torrent.c
  13. +1
    -48
      btpd/torrent.h
  14. +4
    -4
      btpd/tracker_req.c
  15. +7
    -9
      btpd/upload.c
  16. +1
    -1
      btpd/upload.h

+ 1
- 1
btpd/Makefile.am Parādīt failu

@@ -5,7 +5,7 @@ btpd_SOURCES=\
download.c download_subr.c download.h\
http.c http.h\
main.c\
net.c net.h\
net.c net.h net_types.h\
net_buf.c net_buf.h\
opts.c opts.h\
peer.c peer.h\


+ 1
- 0
btpd/btpd.h Parādīt failu

@@ -19,6 +19,7 @@
#include "metainfo.h"
#include "iobuf.h"
#include "net_buf.h"
#include "net_types.h"
#include "net.h"
#include "peer.h"
#include "torrent.h"


+ 2
- 2
btpd/content.c Parādīt failu

@@ -104,8 +104,8 @@ static
void test_cb(int fd, short type, void *arg)
{
struct test *t = arg;
set_bit(t->pc->tp->cm->piece_field, t->pc->index);
t->pc->tp->cm->npieces++;
set_bit(t->pc->n->tp->cm->piece_field, t->pc->index);
t->pc->n->tp->cm->npieces++;
dl_on_ok_piece(t->pc);
free(t);
}


+ 28
- 47
btpd/download.c Parādīt failu

@@ -3,25 +3,6 @@
#include "btpd.h"
#include "tracker_req.h"

void
dl_start(struct torrent *tp)
{
BTPDQ_INIT(&tp->getlst);
tp->busy_field = btpd_calloc((size_t)ceil(tp->meta.npieces / 8.0), 1);
tp->piece_count = btpd_calloc(tp->meta.npieces,
sizeof(*(tp->piece_count)));
}

void
dl_stop(struct torrent *tp)
{
struct piece *pc;
while ((pc = BTPDQ_FIRST(&tp->getlst)) != NULL)
piece_free(pc);
free(tp->busy_field);
free(tp->piece_count);
}

/*
* Called when a peer announces it's got a new piece.
*
@@ -31,12 +12,12 @@ dl_stop(struct torrent *tp)
void
dl_on_piece_ann(struct peer *p, uint32_t index)
{
struct torrent *tp = p->tp;
tp->piece_count[index]++;
if (cm_has_piece(tp, index))
struct net *n = p->n;
n->piece_count[index]++;
if (cm_has_piece(n->tp, index))
return;
struct piece *pc = dl_find_piece(tp, index);
if (tp->endgame) {
struct piece *pc = dl_find_piece(n, index);
if (n->endgame) {
assert(pc != NULL);
peer_want(p, index);
if (!peer_chokes(p) && !peer_laden(p))
@@ -44,7 +25,7 @@ dl_on_piece_ann(struct peer *p, uint32_t index)
} else if (pc == NULL) {
peer_want(p, index);
if (!peer_chokes(p) && !peer_laden(p)) {
pc = dl_new_piece(tp, index);
pc = dl_new_piece(n, index);
if (pc != NULL)
dl_piece_assign_requests(pc, p);
}
@@ -59,12 +40,12 @@ void
dl_on_download(struct peer *p)
{
assert(peer_wanted(p));
struct torrent *tp = p->tp;
if (tp->endgame) {
struct net *n = p->n;
if (n->endgame) {
dl_assign_requests_eg(p);
} else {
unsigned count = dl_assign_requests(p);
if (count == 0 && !p->tp->endgame) // We may have entered end game.
if (count == 0 && !p->n->endgame) // We may have entered end game.
assert(!peer_wanted(p) || peer_laden(p));
}
}
@@ -79,7 +60,7 @@ dl_on_unchoke(struct peer *p)
void
dl_on_undownload(struct peer *p)
{
if (!p->tp->endgame)
if (!p->n->endgame)
dl_unassign_requests(p);
else
dl_unassign_requests_eg(p);
@@ -99,26 +80,26 @@ void
dl_on_ok_piece(struct piece *pc)
{
struct peer *p;
struct torrent *tp = pc->tp;
struct net *n = pc->n;

btpd_log(BTPD_L_POL, "Got piece: %u.\n", pc->index);

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

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

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

if (cm_full(tp)) {
btpd_log(BTPD_L_BTPD, "Finished: %s.\n", tp->relpath);
tr_complete(tp);
BTPDQ_FOREACH(p, &tp->peers, p_entry)
if (cm_full(n->tp)) {
btpd_log(BTPD_L_BTPD, "Finished: %s.\n", n->tp->relpath);
tr_complete(n->tp);
BTPDQ_FOREACH(p, &n->peers, p_entry)
assert(p->nwant == 0);
}
}
@@ -129,10 +110,10 @@ dl_on_ok_piece(struct piece *pc)
void
dl_on_bad_piece(struct piece *pc)
{
struct torrent *tp = pc->tp;
struct net *n = pc->n;

btpd_log(BTPD_L_ERROR, "Bad hash for piece %u of %s.\n",
pc->index, tp->relpath);
pc->index, n->tp->relpath);

for (uint32_t i = 0; i < pc->nblocks; i++)
clear_bit(pc->down_field, i);
@@ -140,9 +121,9 @@ dl_on_bad_piece(struct piece *pc)
pc->ngot = 0;
pc->nbusy = 0;

if (tp->endgame) {
if (n->endgame) {
struct peer *p;
BTPDQ_FOREACH(p, &tp->peers, p_entry) {
BTPDQ_FOREACH(p, &n->peers, p_entry) {
if (peer_has(p, pc->index) && peer_leech_ok(p) && !peer_laden(p))
dl_assign_requests_eg(p);
}
@@ -158,11 +139,11 @@ dl_on_new_peer(struct peer *p)
void
dl_on_lost_peer(struct peer *p)
{
struct torrent *tp = p->tp;
struct net *n = p->n;

for (uint32_t i = 0; i < tp->meta.npieces; i++)
for (uint32_t i = 0; i < n->tp->meta.npieces; i++)
if (peer_has(p, i))
tp->piece_count[i]--;
n->piece_count[i]--;

if (p->nreqs_out > 0)
dl_on_undownload(p);
@@ -172,14 +153,14 @@ void
dl_on_block(struct peer *p, struct block_request *req,
uint32_t index, uint32_t begin, uint32_t length, const char *data)
{
struct torrent *tp = p->tp;
struct net *n = p->n;
struct block *blk = req->blk;
struct piece *pc = blk->pc;

cm_put_block(p->tp, index, begin / PIECE_BLOCKLEN, data);
cm_put_block(p->n->tp, index, begin / PIECE_BLOCKLEN, data);
pc->ngot++;

if (tp->endgame) {
if (n->endgame) {
struct block_request *req;
struct net_buf *cancel = nb_create_cancel(index, begin, length);
nb_hold(cancel);


+ 2
- 5
btpd/download.h Parādīt failu

@@ -8,8 +8,8 @@ void piece_free(struct piece *pc);

void dl_on_piece_unfull(struct piece *pc);

struct piece *dl_new_piece(struct torrent *tp, uint32_t index);
struct piece *dl_find_piece(struct torrent *tp, uint32_t index);
struct piece *dl_new_piece(struct net *n, uint32_t index);
struct piece *dl_find_piece(struct net *n, uint32_t index);
unsigned dl_piece_assign_requests(struct piece *pc, struct peer *p);
unsigned dl_assign_requests(struct peer *p);
void dl_assign_requests_eg(struct peer *p);
@@ -19,9 +19,6 @@ void dl_piece_reorder_eg(struct piece *pc);

// download.c

void dl_start(struct torrent *tp);
void dl_stop(struct torrent *tp);

void dl_on_new_peer(struct peer *p);
void dl_on_lost_peer(struct peer *p);



+ 57
- 57
btpd/download_subr.c Parādīt failu

@@ -30,14 +30,14 @@
#include "stream.h"

static struct piece *
piece_alloc(struct torrent *tp, uint32_t index)
piece_alloc(struct net *n, uint32_t index)
{
assert(!has_bit(tp->busy_field, index)
&& tp->npcs_busy < tp->meta.npieces);
assert(!has_bit(n->busy_field, index)
&& n->npcs_busy < n->tp->meta.npieces);
struct piece *pc;
size_t mem, field, blocks;
unsigned nblocks;
off_t piece_length = torrent_piece_size(tp, index);
off_t piece_length = torrent_piece_size(n->tp, index);

nblocks = (unsigned)ceil((double)piece_length / PIECE_BLOCKLEN);
blocks = sizeof(pc->blocks[0]) * nblocks;
@@ -45,9 +45,9 @@ piece_alloc(struct torrent *tp, uint32_t index)
mem = sizeof(*pc) + field + blocks;

pc = btpd_calloc(1, mem);
pc->tp = tp;
pc->n = n;
pc->down_field = (uint8_t *)(pc + 1);
pc->have_field = cm_get_block_field(tp, index);
pc->have_field = cm_get_block_field(n->tp, index);

pc->index = index;
pc->nblocks = nblocks;
@@ -71,20 +71,20 @@ piece_alloc(struct torrent *tp, uint32_t index)
nb_hold(blk->msg);
}

tp->npcs_busy++;
set_bit(tp->busy_field, index);
BTPDQ_INSERT_HEAD(&tp->getlst, pc, entry);
n->npcs_busy++;
set_bit(n->busy_field, index);
BTPDQ_INSERT_HEAD(&n->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);
struct net *n = pc->n;
assert(n->npcs_busy > 0);
n->npcs_busy--;
clear_bit(n->busy_field, pc->index);
BTPDQ_REMOVE(&pc->n->getlst, pc, entry);
for (unsigned i = 0; i < pc->nblocks; i++) {
struct block_request *req = BTPDQ_FIRST(&pc->blocks[i].reqs);
while (req != NULL) {
@@ -104,13 +104,13 @@ piece_full(struct piece *pc)
}

static int
dl_should_enter_endgame(struct torrent *tp)
dl_should_enter_endgame(struct net *n)
{
int should;
if (cm_get_npieces(tp) + tp->npcs_busy == tp->meta.npieces) {
if (cm_get_npieces(n->tp) + n->npcs_busy == n->tp->meta.npieces) {
should = 1;
struct piece *pc;
BTPDQ_FOREACH(pc, &tp->getlst, entry) {
BTPDQ_FOREACH(pc, &n->getlst, entry) {
if (!piece_full(pc)) {
should = 0;
break;
@@ -124,7 +124,7 @@ dl_should_enter_endgame(struct torrent *tp)
static void
dl_piece_insert_eg(struct piece *pc)
{
struct piece_tq *getlst = &pc->tp->getlst;
struct piece_tq *getlst = &pc->n->getlst;
if (pc->nblocks == pc->ngot)
BTPDQ_INSERT_TAIL(getlst, pc, entry);
else {
@@ -145,37 +145,37 @@ dl_piece_insert_eg(struct piece *pc)
void
dl_piece_reorder_eg(struct piece *pc)
{
BTPDQ_REMOVE(&pc->tp->getlst, pc, entry);
BTPDQ_REMOVE(&pc->n->getlst, pc, entry);
dl_piece_insert_eg(pc);
}

static void
dl_enter_endgame(struct torrent *tp)
dl_enter_endgame(struct net *n)
{
struct peer *p;
struct piece *pc;
struct piece *pcs[tp->npcs_busy];
struct piece *pcs[n->npcs_busy];
unsigned pi;

btpd_log(BTPD_L_POL, "Entering end game\n");
tp->endgame = 1;
n->endgame = 1;

pi = 0;
BTPDQ_FOREACH(pc, &tp->getlst, entry) {
BTPDQ_FOREACH(pc, &n->getlst, entry) {
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);
BTPDQ_INIT(&n->getlst);
while (pi > 0) {
pi--;
dl_piece_insert_eg(pcs[pi]);
}
BTPDQ_FOREACH(p, &tp->peers, p_entry) {
BTPDQ_FOREACH(p, &n->peers, p_entry) {
assert(p->nwant == 0);
BTPDQ_FOREACH(pc, &tp->getlst, entry) {
BTPDQ_FOREACH(pc, &n->getlst, entry) {
if (peer_has(p, pc->index))
peer_want(p, pc->index);
}
@@ -185,10 +185,10 @@ dl_enter_endgame(struct torrent *tp)
}

struct piece *
dl_find_piece(struct torrent *tp, uint32_t index)
dl_find_piece(struct net *n, uint32_t index)
{
struct piece *pc;
BTPDQ_FOREACH(pc, &tp->getlst, entry)
BTPDQ_FOREACH(pc, &n->getlst, entry)
if (pc->index == index)
break;
return pc;
@@ -197,8 +197,8 @@ dl_find_piece(struct torrent *tp, uint32_t index)
static int
dl_piece_startable(struct peer *p, uint32_t index)
{
return peer_has(p, index) && !cm_has_piece(p->tp, index)
&& !has_bit(p->tp->busy_field, index);
return peer_has(p, index) && !cm_has_piece(p->n->tp, index)
&& !has_bit(p->n->busy_field, index);
}

/*
@@ -212,23 +212,23 @@ static int
dl_choose_rarest(struct peer *p, uint32_t *res)
{
uint32_t i;
struct torrent *tp = p->tp;
struct net *n = p->n;

assert(tp->endgame == 0);
assert(n->endgame == 0);

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

if (i == tp->meta.npieces)
if (i == n->tp->meta.npieces)
return ENOENT;

uint32_t min_i = i;
uint32_t min_c = 1;
for(i++; i < tp->meta.npieces; i++) {
for(i++; i < n->tp->meta.npieces; i++) {
if (dl_piece_startable(p, i)) {
if (tp->piece_count[i] == tp->piece_count[min_i])
if (n->piece_count[i] == n->piece_count[min_i])
min_c++;
else if (tp->piece_count[i] < tp->piece_count[min_i]) {
else if (n->piece_count[i] < n->piece_count[min_i]) {
min_i = i;
min_c = 1;
}
@@ -238,7 +238,7 @@ dl_choose_rarest(struct peer *p, uint32_t *res)
min_c = rand_between(1, min_c);
for (i = min_i; min_c > 0; i++) {
if (dl_piece_startable(p, i)
&& tp->piece_count[i] == tp->piece_count[min_i]) {
&& n->piece_count[i] == n->piece_count[min_i]) {
min_c--;
min_i = i;
}
@@ -257,12 +257,12 @@ static void
dl_on_piece_full(struct piece *pc)
{
struct peer *p;
BTPDQ_FOREACH(p, &pc->tp->peers, p_entry) {
BTPDQ_FOREACH(p, &pc->n->peers, p_entry) {
if (peer_has(p, pc->index))
peer_unwant(p, pc->index);
}
if (dl_should_enter_endgame(pc->tp))
dl_enter_endgame(pc->tp);
if (dl_should_enter_endgame(pc->n))
dl_enter_endgame(pc->n);
}

/*
@@ -275,10 +275,10 @@ dl_on_piece_full(struct piece *pc)
* Return the piece or NULL.
*/
struct piece *
dl_new_piece(struct torrent *tp, uint32_t index)
dl_new_piece(struct net *n, uint32_t index)
{
btpd_log(BTPD_L_POL, "Started on piece %u.\n", index);
return piece_alloc(tp, index);
return piece_alloc(n, index);
}

/*
@@ -291,13 +291,13 @@ dl_new_piece(struct torrent *tp, uint32_t index)
void
dl_on_piece_unfull(struct piece *pc)
{
struct torrent *tp = pc->tp;
struct net *n = pc->n;
struct peer *p;
assert(!piece_full(pc) && tp->endgame == 0);
BTPDQ_FOREACH(p, &tp->peers, p_entry)
assert(!piece_full(pc) && n->endgame == 0);
BTPDQ_FOREACH(p, &n->peers, p_entry)
if (peer_has(p, pc->index))
peer_want(p, pc->index);
p = BTPDQ_FIRST(&tp->peers);
p = BTPDQ_FIRST(&n->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.
@@ -360,25 +360,25 @@ dl_piece_assign_requests(struct piece *pc, struct peer *p)
unsigned
dl_assign_requests(struct peer *p)
{
assert(!p->tp->endgame && !peer_laden(p));
assert(!p->n->endgame && !peer_laden(p));
struct piece *pc;
struct torrent *tp = p->tp;
struct net *n = p->n;
unsigned count = 0;
BTPDQ_FOREACH(pc, &tp->getlst, entry) {
BTPDQ_FOREACH(pc, &n->getlst, entry) {
if (piece_full(pc) || !peer_has(p, pc->index))
continue;
count += dl_piece_assign_requests(pc, p);
if (tp->endgame)
if (n->endgame)
break;
if (!piece_full(pc))
assert(peer_laden(p));
if (peer_laden(p))
break;
}
while (!peer_laden(p) && !tp->endgame) {
while (!peer_laden(p) && !n->endgame) {
uint32_t index;
if (dl_choose_rarest(p, &index) == 0) {
pc = dl_new_piece(tp, index);
pc = dl_new_piece(n, index);
if (pc != NULL)
count += dl_piece_assign_requests(pc, p);
} else
@@ -445,16 +445,16 @@ void
dl_assign_requests_eg(struct peer *p)
{
assert(!peer_laden(p));
struct torrent *tp = p->tp;
struct net *n = p->n;
struct piece_tq tmp;
BTPDQ_INIT(&tmp);

struct piece *pc = BTPDQ_FIRST(&tp->getlst);
struct piece *pc = BTPDQ_FIRST(&n->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_REMOVE(&n->getlst, pc, entry);
BTPDQ_INSERT_HEAD(&tmp, pc, entry);
}
pc = next;
@@ -480,7 +480,7 @@ dl_unassign_requests_eg(struct peer *p)
req = BTPDQ_FIRST(&p->my_reqs);

pc = req->blk->pc;
BTPDQ_REMOVE(&pc->tp->getlst, pc, entry);
BTPDQ_REMOVE(&pc->n->getlst, pc, entry);
BTPDQ_INSERT_HEAD(&tmp, pc, entry);

while (req != NULL) {


+ 66
- 32
btpd/net.c Parādīt failu

@@ -18,8 +18,6 @@

#include "btpd.h"

#define min(x, y) ((x) <= (y) ? (x) : (y))

static struct event m_bw_timer;
static unsigned long m_bw_bytes_in;
static unsigned long m_bw_bytes_out;
@@ -30,7 +28,7 @@ static unsigned long m_rate_dwn;
static struct event m_net_incoming;

static unsigned m_ntorrents;
static struct torrent_tq m_torrents = BTPDQ_HEAD_INITIALIZER(m_torrents);
static struct net_tq m_torrents = BTPDQ_HEAD_INITIALIZER(m_torrents);

unsigned net_npeers;

@@ -38,40 +36,76 @@ struct peer_tq net_bw_readq = BTPDQ_HEAD_INITIALIZER(net_bw_readq);
struct peer_tq net_bw_writeq = BTPDQ_HEAD_INITIALIZER(net_bw_writeq);
struct peer_tq net_unattached = BTPDQ_HEAD_INITIALIZER(net_unattached);

int
net_torrent_has_peer(struct net *n, const uint8_t *id)
{
int has = 0;
struct peer *p = BTPDQ_FIRST(&n->peers);
while (p != NULL) {
if (bcmp(p->id, id, 20) == 0) {
has = 1;
break;
}
p = BTPDQ_NEXT(p, p_entry);
}
return has;
}

void
net_add_torrent(struct torrent *tp)
{
tp->net_active = 1;
BTPDQ_INSERT_HEAD(&m_torrents, tp, net_entry);
size_t field_size = ceil(tp->meta.npieces / 8.0);
size_t mem = sizeof(*(tp->net)) + field_size +
tp->meta.npieces * sizeof(*(tp->net->piece_count));

struct net *n = btpd_calloc(1, mem);
n->tp = tp;
tp->net = n;

n->active = 1;
BTPDQ_INIT(&n->getlst);

n->busy_field = (uint8_t *)(n + 1);
n->piece_count = (unsigned *)(n->busy_field + field_size);

BTPDQ_INSERT_HEAD(&m_torrents, n, entry);
m_ntorrents++;
dl_start(tp);
}

void
net_del_torrent(struct torrent *tp)
{
tp->net_active = 0;
struct net *n = tp->net;
tp->net = NULL;

assert(m_ntorrents > 0);
m_ntorrents--;
BTPDQ_REMOVE(&m_torrents, tp, net_entry);
BTPDQ_REMOVE(&m_torrents, n, entry);

n->active = 0;

ul_on_lost_torrent(tp);
dl_stop(tp);
ul_on_lost_torrent(n);

struct piece *pc;
while ((pc = BTPDQ_FIRST(&n->getlst)) != NULL)
piece_free(pc);

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

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

free(n);
}

void
@@ -142,7 +176,7 @@ net_write(struct peer *p, unsigned long wmax)
if (bcount >= bufdelta) {
peer_sent(p, nl->nb);
if (nl->nb->type == NB_TORRENTDATA) {
p->tp->uploaded += bufdelta;
p->n->uploaded += bufdelta;
p->count_up += bufdelta;
}
bcount -= bufdelta;
@@ -153,7 +187,7 @@ net_write(struct peer *p, unsigned long wmax)
nl = BTPDQ_FIRST(&p->outq);
} else {
if (nl->nb->type == NB_TORRENTDATA) {
p->tp->uploaded += bcount;
p->n->uploaded += bcount;
p->count_up += bcount;
}
p->outq_off += bcount;
@@ -200,9 +234,9 @@ net_dispatch_msg(struct peer *p, const char *buf)
begin = net_read32(buf + 4);
length = net_read32(buf + 8);
if ((length > PIECE_BLOCKLEN
|| index >= p->tp->meta.npieces
|| cm_has_piece(p->tp, index)
|| begin + length > torrent_piece_size(p->tp, index))) {
|| index >= p->n->tp->meta.npieces
|| cm_has_piece(p->n->tp, index)
|| begin + length > torrent_piece_size(p->n->tp, index))) {
btpd_log(BTPD_L_MSG, "bad request: (%u, %u, %u) from %p\n",
index, begin, length, p);
res = 1;
@@ -240,7 +274,7 @@ net_mh_ok(struct peer *p)
case MSG_HAVE:
return mlen == 5;
case MSG_BITFIELD:
return mlen == (uint32_t)ceil(p->tp->meta.npieces / 8.0) + 1;
return mlen == (uint32_t)ceil(p->n->tp->meta.npieces / 8.0) + 1;
case MSG_REQUEST:
case MSG_CANCEL:
return mlen == 13;
@@ -255,7 +289,7 @@ static void
net_progress(struct peer *p, size_t length)
{
if (p->in.state == BTP_MSGBODY && p->in.msg_num == MSG_PIECE) {
p->tp->downloaded += length;
p->n->downloaded += length;
p->count_dwn += length;
}
}
@@ -271,20 +305,20 @@ net_state(struct peer *p, const char *buf)
break;
case SHAKE_INFO:
if (p->flags & PF_INCOMING) {
struct torrent *tp;
BTPDQ_FOREACH(tp, &m_torrents, net_entry)
if (bcmp(buf, tp->meta.info_hash, 20) == 0)
struct net *n;
BTPDQ_FOREACH(n, &m_torrents, entry)
if (bcmp(buf, n->tp->meta.info_hash, 20) == 0)
break;
if (tp == NULL)
if (n == 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)
p->n = n;
peer_send(p, nb_create_shake(p->n->tp));
} else if (bcmp(buf, p->n->tp->meta.info_hash, 20) != 0)
goto bad;
peer_set_in_state(p, SHAKE_ID, 20);
break;
case SHAKE_ID:
if ((torrent_has_peer(p->tp, buf)
if ((net_torrent_has_peer(p->n, buf)
|| bcmp(buf, btpd_get_peer_id(), 20) == 0))
goto bad;
bcopy(buf, p->id, 20);
@@ -487,11 +521,11 @@ compute_rate_sub(unsigned long rate)
static void
compute_rates(void) {
unsigned long tot_up = 0, tot_dwn = 0;
struct torrent *tp;
BTPDQ_FOREACH(tp, &m_torrents, net_entry) {
struct net *n;
BTPDQ_FOREACH(n, &m_torrents, entry) {
unsigned long tp_up = 0, tp_dwn = 0;
struct peer *p;
BTPDQ_FOREACH(p, &tp->peers, p_entry) {
BTPDQ_FOREACH(p, &n->peers, p_entry) {
if (p->count_up > 0 || peer_active_up(p)) {
tp_up += p->count_up;
p->rate_up += p->count_up - compute_rate_sub(p->rate_up);
@@ -503,8 +537,8 @@ compute_rates(void) {
p->count_dwn = 0;
}
}
tp->rate_up += tp_up - compute_rate_sub(tp->rate_up);
tp->rate_dwn += tp_dwn - compute_rate_sub(tp->rate_dwn);
n->rate_up += tp_up - compute_rate_sub(n->rate_up);
n->rate_dwn += tp_dwn - compute_rate_sub(n->rate_dwn);
tot_up += tp_up;
tot_dwn += tp_dwn;
}


+ 2
- 0
btpd/net.h Parādīt failu

@@ -23,6 +23,8 @@ void net_init(void);
void net_add_torrent(struct torrent *tp);
void net_del_torrent(struct torrent *tp);

int net_torrent_has_peer(struct net *n, const uint8_t *id);

void net_read_cb(int sd, short type, void *arg);
void net_write_cb(int sd, short type, void *arg);



+ 114
- 0
btpd/net_types.h Parādīt failu

@@ -0,0 +1,114 @@
#ifndef BTPD_NET_TYPES_H
#define BTPD_NET_TYPES_H

BTPDQ_HEAD(net_tq, net);
BTPDQ_HEAD(peer_tq, peer);
BTPDQ_HEAD(piece_tq, piece);
BTPDQ_HEAD(block_request_tq, block_request);

struct net {
struct torrent *tp;

int active;
int endgame;

uint8_t *busy_field;
uint32_t npcs_busy;
unsigned *piece_count;
struct piece_tq getlst;

uint64_t uploaded, downloaded;
unsigned long rate_up, rate_dwn;

unsigned npeers;
struct peer_tq peers;

BTPDQ_ENTRY(net) entry;
};

enum input_state {
SHAKE_PSTR,
SHAKE_INFO,
SHAKE_ID,
BTP_MSGSIZE,
BTP_MSGHEAD,
BTP_PIECEMETA,
BTP_MSGBODY
};

struct peer {
int sd;
uint16_t flags;
uint8_t *piece_field;
uint32_t npieces;
uint32_t nwant;

uint8_t id[20];

struct net *n;

struct block_request_tq my_reqs;

unsigned nreqs_out;
unsigned npiece_msgs;

size_t outq_off;
struct nb_tq outq;

struct event in_ev;
struct event out_ev;

unsigned long rate_up, rate_dwn;
unsigned long count_up, count_dwn;

struct {
uint32_t msg_len;
uint8_t msg_num;
uint32_t pc_index;
uint32_t pc_begin;
enum input_state state;
size_t st_bytes;
char *buf;
size_t off;
} in;

BTPDQ_ENTRY(peer) p_entry;
BTPDQ_ENTRY(peer) ul_entry;
BTPDQ_ENTRY(peer) rq_entry;
BTPDQ_ENTRY(peer) wq_entry;
};

struct piece {
struct net *n;

uint32_t index;

unsigned nreqs;

unsigned nblocks;
unsigned ngot;
unsigned nbusy;
unsigned next_block;

struct block *blocks;

const uint8_t *have_field;
uint8_t *down_field;

BTPDQ_ENTRY(piece) entry;
};

struct block {
struct piece *pc;
struct net_buf *msg;
struct block_request_tq reqs;
};

struct block_request {
struct peer *p;
struct block *blk;
BTPDQ_ENTRY(block_request) p_entry;
BTPDQ_ENTRY(block_request) blk_entry;
};

#endif

+ 21
- 20
btpd/peer.c Parādīt failu

@@ -17,12 +17,12 @@ peer_kill(struct peer *p)
btpd_log(BTPD_L_CONN, "killed peer %p\n", p);

if (p->flags & PF_ATTACHED) {
if (p->tp->net_active) {
if (p->n->active) {
ul_on_lost_peer(p);
dl_on_lost_peer(p);
}
BTPDQ_REMOVE(&p->tp->peers, p, p_entry);
p->tp->npeers--;
BTPDQ_REMOVE(&p->n->peers, p, p_entry);
p->n->npeers--;
} else
BTPDQ_REMOVE(&net_unattached, p, p_entry);
if (p->flags & PF_ON_READQ)
@@ -284,7 +284,7 @@ peer_create_in(int sd)
}

void
peer_create_out(struct torrent *tp, const uint8_t *id,
peer_create_out(struct net *n, const uint8_t *id,
const char *ip, int port)
{
int sd;
@@ -294,12 +294,12 @@ peer_create_out(struct torrent *tp, const uint8_t *id,
return;

p = peer_create_common(sd);
p->tp = tp;
peer_send(p, nb_create_shake(p->tp));
p->n = n;
peer_send(p, nb_create_shake(n->tp));
}

void
peer_create_out_compact(struct torrent *tp, const char *compact)
peer_create_out_compact(struct net *n, const char *compact)
{
int sd;
struct peer *p;
@@ -313,8 +313,8 @@ peer_create_out_compact(struct torrent *tp, const char *compact)
return;

p = peer_create_common(sd);
p->tp = tp;
peer_send(p, nb_create_shake(p->tp));
p->n = n;
peer_send(p, nb_create_shake(n->tp));
}

void
@@ -342,20 +342,21 @@ peer_on_shake(struct peer *p)
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));
if (cm_get_npieces(p->tp) > 0) {
if (cm_get_npieces(p->tp) * 9 < 5 + ceil(p->tp->meta.npieces / 8.0))
peer_send(p, nb_create_multihave(p->tp));
p->piece_field = btpd_calloc(1, (int)ceil(p->n->tp->meta.npieces / 8.0));
if (cm_get_npieces(p->n->tp) > 0) {
if ((cm_get_npieces(p->n->tp) * 9 < 5 +
ceil(p->n->tp->meta.npieces / 8.0)))
peer_send(p, nb_create_multihave(p->n->tp));
else {
peer_send(p, nb_create_bitfield(p->tp));
peer_send(p, nb_create_bitdata(p->tp));
peer_send(p, nb_create_bitfield(p->n->tp));
peer_send(p, nb_create_bitdata(p->n->tp));
}
}

BTPDQ_REMOVE(&net_unattached, p, p_entry);
BTPDQ_INSERT_HEAD(&p->tp->peers, p, p_entry);
BTPDQ_INSERT_HEAD(&p->n->peers, p, p_entry);
p->flags |= PF_ATTACHED;
p->tp->npeers++;
p->n->npeers++;

ul_on_new_peer(p);
dl_on_new_peer(p);
@@ -434,8 +435,8 @@ peer_on_bitfield(struct peer *p, const uint8_t *field)
{
btpd_log(BTPD_L_MSG, "received bitfield from %p\n", p);
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++) {
bcopy(field, p->piece_field, (size_t)ceil(p->n->tp->meta.npieces / 8.0));
for (uint32_t i = 0; i < p->n->tp->meta.npieces; i++) {
if (has_bit(p->piece_field, i)) {
p->npieces++;
dl_on_piece_ann(p, i);
@@ -475,7 +476,7 @@ peer_on_request(struct peer *p, uint32_t index, uint32_t begin,
index, begin, length, p);
if ((p->flags & PF_NO_REQUESTS) == 0) {
char *content;
if (cm_get_bytes(p->tp, index, begin, length, &content) == 0) {
if (cm_get_bytes(p->n->tp, index, begin, length, &content) == 0) {
peer_send(p, nb_create_piece(index, begin, length));
peer_send(p, nb_create_torrentdata(content, length));
p->npiece_msgs++;


+ 2
- 65
btpd/peer.h Parādīt failu

@@ -15,69 +15,6 @@
#define MAXPIECEMSGS 128
#define MAXPIPEDREQUESTS 10

struct block_request {
struct peer *p;
struct block *blk;
BTPDQ_ENTRY(block_request) p_entry;
BTPDQ_ENTRY(block_request) blk_entry;
};

BTPDQ_HEAD(block_request_tq, block_request);

enum input_state {
SHAKE_PSTR,
SHAKE_INFO,
SHAKE_ID,
BTP_MSGSIZE,
BTP_MSGHEAD,
BTP_PIECEMETA,
BTP_MSGBODY
};

struct peer {
int sd;
uint16_t flags;
uint8_t *piece_field;
uint32_t npieces;
uint32_t nwant;

uint8_t id[20];

struct torrent *tp;

struct block_request_tq my_reqs;

unsigned nreqs_out;
unsigned npiece_msgs;

size_t outq_off;
struct nb_tq outq;

struct event in_ev;
struct event out_ev;

unsigned long rate_up, rate_dwn;
unsigned long count_up, count_dwn;

struct {
uint32_t msg_len;
uint8_t msg_num;
uint32_t pc_index;
uint32_t pc_begin;
enum input_state state;
size_t st_bytes;
char *buf;
size_t off;
} in;

BTPDQ_ENTRY(peer) p_entry;
BTPDQ_ENTRY(peer) ul_entry;
BTPDQ_ENTRY(peer) rq_entry;
BTPDQ_ENTRY(peer) wq_entry;
};

BTPDQ_HEAD(peer_tq, peer);

void peer_set_in_state(struct peer *p, enum input_state state, size_t size);

void peer_send(struct peer *p, struct net_buf *nb);
@@ -95,9 +32,9 @@ void peer_cancel(struct peer *p, struct block_request *req,
int peer_requested(struct peer *p, struct block *blk);

void peer_create_in(int sd);
void peer_create_out(struct torrent *tp, const uint8_t *id,
void peer_create_out(struct net *n, const uint8_t *id,
const char *ip, int port);
void peer_create_out_compact(struct torrent *tp, const char *compact);
void peer_create_out_compact(struct net *n, const char *compact);
void peer_kill(struct peer *p);

void peer_on_no_reqs(struct peer *p);


+ 1
- 16
btpd/torrent.c Parādīt failu

@@ -19,21 +19,6 @@
#include "tracker_req.h"
#include "stream.h"

int
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);
}
return has;
}

off_t
torrent_piece_size(struct torrent *tp, uint32_t index)
{
@@ -52,7 +37,7 @@ torrent_block_size(struct piece *pc, uint32_t index)
return PIECE_BLOCKLEN;
else {
uint32_t allbutlast = PIECE_BLOCKLEN * (pc->nblocks - 1);
return torrent_piece_size(pc->tp, pc->index) - allbutlast;
return torrent_piece_size(pc->n->tp, pc->index) - allbutlast;
}
}



+ 1
- 48
btpd/torrent.h Parādīt failu

@@ -3,34 +3,6 @@

#define PIECE_BLOCKLEN (1 << 14)

struct block {
struct piece *pc;
struct net_buf *msg;
struct block_request_tq reqs;
};

struct piece {
struct torrent *tp;

uint32_t index;

unsigned nreqs;

unsigned nblocks;
unsigned ngot;
unsigned nbusy;
unsigned next_block;

struct block *blocks;

const uint8_t *have_field;
uint8_t *down_field;

BTPDQ_ENTRY(piece) entry;
};

BTPDQ_HEAD(piece_tq, piece);

enum torrent_state {
T_INACTIVE,
T_STARTING,
@@ -46,26 +18,9 @@ struct torrent {

struct content *cm;
struct tracker *tr;
struct net *net;

BTPDQ_ENTRY(torrent) entry;
BTPDQ_ENTRY(torrent) net_entry;

int net_active;

uint8_t *busy_field;
uint32_t npcs_busy;

unsigned *piece_count;

uint64_t uploaded, downloaded;

unsigned long rate_up, rate_dwn;

unsigned npeers;
struct peer_tq peers;

int endgame;
struct piece_tq getlst;
};

BTPDQ_HEAD(torrent_tq, torrent);
@@ -74,8 +29,6 @@ int torrent_create(struct torrent **res, const char *path);
void torrent_activate(struct torrent *tp);
void torrent_deactivate(struct torrent *tp);

int torrent_has_peer(struct torrent *tp, const uint8_t *id);

off_t torrent_piece_size(struct torrent *tp, uint32_t index);
uint32_t torrent_block_size(struct piece *pc, uint32_t index);



+ 4
- 4
btpd/tracker_req.c Parādīt failu

@@ -61,7 +61,7 @@ maybe_connect_to(struct torrent *tp, const char *pinfo)
if (bcmp(btpd_get_peer_id(), pid, 20) == 0)
return;

if (torrent_has_peer(tp, pid))
if (net_torrent_has_peer(tp->net, pid))
return;

if (benc_dget_strz(pinfo, "ip", &ip, NULL) != 0)
@@ -70,7 +70,7 @@ maybe_connect_to(struct torrent *tp, const char *pinfo)
if (benc_dget_int64(pinfo, "port", &port) != 0)
goto out;

peer_create_out(tp, pid, ip, port);
peer_create_out(tp->net, pid, ip, port);

out:
if (ip != NULL)
@@ -118,7 +118,7 @@ parse_reply(struct torrent *tp, const char *content, size_t size)
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->net, peers + i);
}
}

@@ -218,7 +218,7 @@ tr_send(struct torrent *tp, enum tr_event event)
"%s%cinfo_hash=%s&peer_id=%s&port=%d&uploaded=%ju"
"&downloaded=%ju&left=%ju&compact=1%s%s",
tp->meta.announce, qc, e_hash, e_id, net_port,
(intmax_t)tp->uploaded, (intmax_t)tp->downloaded,
(intmax_t)tp->net->uploaded, (intmax_t)tp->net->downloaded,
(intmax_t)cm_bytes_left(tp),
event == TR_EV_EMPTY ? "" : "&event=", m_events[event]);
}


+ 7
- 9
btpd/upload.c Parādīt failu

@@ -19,8 +19,8 @@ rate_cmp(const void *arg1, const void *arg2)
{
struct peer *p1 = (*(struct peer_sort **)arg1)->p;
struct peer *p2 = (*(struct peer_sort **)arg2)->p;
unsigned long rate1 = cm_full(p1->tp) ? p1->rate_up : p1->rate_dwn;
unsigned long rate2 = cm_full(p2->tp) ? p2->rate_up : p2->rate_dwn;
unsigned long rate1 = cm_full(p1->n->tp) ? p1->rate_up : p1->rate_dwn;
unsigned long rate2 = cm_full(p2->n->tp) ? p2->rate_up : p2->rate_dwn;
if (rate1 < rate2)
return -1;
else if (rate1 == rate2)
@@ -51,8 +51,8 @@ choke_do(void)
int unchoked[m_npeers];

BTPDQ_FOREACH(p, &m_peerq, ul_entry) {
if (((cm_full(p->tp) && p->rate_up > 0)
|| (!cm_full(p->tp) && p->rate_dwn > 0))) {
if (((cm_full(p->n->tp) && p->rate_up > 0)
|| (!cm_full(p->n->tp) && p->rate_dwn > 0))) {
worthy[nworthy].p = p;
worthy[nworthy].i = i;
nworthy++;
@@ -143,14 +143,12 @@ ul_on_lost_peer(struct peer *p)
}

void
ul_on_lost_torrent(struct torrent *tp)
ul_on_lost_torrent(struct net *n)
{
struct peer *p = BTPDQ_FIRST(&m_peerq);
while (p != NULL) {
struct peer *next = BTPDQ_NEXT(p, p_entry);
struct peer *p;
BTPDQ_FOREACH(p, &n->peers, p_entry) {
BTPDQ_REMOVE(&m_peerq, p, ul_entry);
m_npeers--;
p = next;
}
choke_do();
}


+ 1
- 1
btpd/upload.h Parādīt failu

@@ -3,7 +3,7 @@

void ul_on_new_peer(struct peer *p);
void ul_on_lost_peer(struct peer *p);
void ul_on_lost_torrent(struct torrent *tp);
void ul_on_lost_torrent(struct net *n);
void ul_on_interest(struct peer *p);
void ul_on_uninterest(struct peer *p);
void ul_init(void);


Notiek ielāde…
Atcelt
Saglabāt