From 2d21101699e34ee1e29d1789771fddbf1733d0a1 Mon Sep 17 00:00:00 2001 From: Richard Nyberg Date: Mon, 9 Jan 2006 21:20:14 +0000 Subject: [PATCH] * 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 --- btpd/Makefile.am | 2 +- btpd/btpd.h | 1 + btpd/content.c | 4 +- btpd/download.c | 75 +++++++++++----------------- btpd/download.h | 7 +-- btpd/download_subr.c | 114 +++++++++++++++++++++---------------------- btpd/net.c | 98 +++++++++++++++++++++++++------------ btpd/net.h | 2 + btpd/net_types.h | 114 +++++++++++++++++++++++++++++++++++++++++++ btpd/peer.c | 41 ++++++++-------- btpd/peer.h | 67 +------------------------ btpd/torrent.c | 17 +------ btpd/torrent.h | 49 +------------------ btpd/tracker_req.c | 8 +-- btpd/upload.c | 16 +++--- btpd/upload.h | 2 +- 16 files changed, 310 insertions(+), 307 deletions(-) create mode 100644 btpd/net_types.h diff --git a/btpd/Makefile.am b/btpd/Makefile.am index cd3870f..ab67b5e 100644 --- a/btpd/Makefile.am +++ b/btpd/Makefile.am @@ -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\ diff --git a/btpd/btpd.h b/btpd/btpd.h index 323c939..c00469d 100644 --- a/btpd/btpd.h +++ b/btpd/btpd.h @@ -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" diff --git a/btpd/content.c b/btpd/content.c index a86a815..06a282d 100644 --- a/btpd/content.c +++ b/btpd/content.c @@ -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); } diff --git a/btpd/download.c b/btpd/download.c index a4398db..5948425 100644 --- a/btpd/download.c +++ b/btpd/download.c @@ -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); diff --git a/btpd/download.h b/btpd/download.h index 94f71da..baeed94 100644 --- a/btpd/download.h +++ b/btpd/download.h @@ -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); diff --git a/btpd/download_subr.c b/btpd/download_subr.c index f1db9a7..225effc 100644 --- a/btpd/download_subr.c +++ b/btpd/download_subr.c @@ -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) { diff --git a/btpd/net.c b/btpd/net.c index cfc6813..fca3143 100644 --- a/btpd/net.c +++ b/btpd/net.c @@ -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; } diff --git a/btpd/net.h b/btpd/net.h index 2fafbcd..6a79b78 100644 --- a/btpd/net.h +++ b/btpd/net.h @@ -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); diff --git a/btpd/net_types.h b/btpd/net_types.h new file mode 100644 index 0000000..6b17bac --- /dev/null +++ b/btpd/net_types.h @@ -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 diff --git a/btpd/peer.c b/btpd/peer.c index 779ae7d..f043056 100644 --- a/btpd/peer.c +++ b/btpd/peer.c @@ -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++; diff --git a/btpd/peer.h b/btpd/peer.h index 722f70e..0921438 100644 --- a/btpd/peer.h +++ b/btpd/peer.h @@ -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); diff --git a/btpd/torrent.c b/btpd/torrent.c index 902e765..909b18b 100644 --- a/btpd/torrent.c +++ b/btpd/torrent.c @@ -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; } } diff --git a/btpd/torrent.h b/btpd/torrent.h index 10d6691..6ce07a4 100644 --- a/btpd/torrent.h +++ b/btpd/torrent.h @@ -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); diff --git a/btpd/tracker_req.c b/btpd/tracker_req.c index db65e54..58246e3 100644 --- a/btpd/tracker_req.c +++ b/btpd/tracker_req.c @@ -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]); } diff --git a/btpd/upload.c b/btpd/upload.c index 5e5174d..7de5243 100644 --- a/btpd/upload.c +++ b/btpd/upload.c @@ -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(); } diff --git a/btpd/upload.h b/btpd/upload.h index 49956ff..43a8560 100644 --- a/btpd/upload.h +++ b/btpd/upload.h @@ -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);