diff --git a/btpd/download.c b/btpd/download.c index 2bb62fc..9ef54be 100644 --- a/btpd/download.c +++ b/btpd/download.c @@ -79,14 +79,17 @@ dl_on_choke(struct peer *p) void dl_on_ok_piece(struct net *n, uint32_t piece) { - struct peer *p; + struct peer *p, *next; struct piece *pc = dl_find_piece(n, piece); btpd_log(BTPD_L_POL, "Got piece: %u.\n", pc->index); struct net_buf *have = nb_create_have(pc->index); + nb_hold(have); BTPDQ_FOREACH(p, &n->peers, p_entry) - peer_send(p, have); + if (!peer_has(p, pc->index)) + peer_send(p, have); + nb_drop(have); if (n->endgame) BTPDQ_FOREACH(p, &n->peers, p_entry) @@ -100,8 +103,11 @@ dl_on_ok_piece(struct net *n, uint32_t piece) btpd_log(BTPD_L_BTPD, "Finished downloading '%s'.\n", torrent_name(n->tp)); tr_complete(n->tp); - BTPDQ_FOREACH(p, &n->peers, p_entry) + BTPDQ_FOREACH_MUTABLE(p, &n->peers, p_entry, next) { assert(p->nwant == 0); + if (peer_full(p)) + peer_kill(p); + } } } diff --git a/btpd/net_types.h b/btpd/net_types.h index b444eea..9ade854 100644 --- a/btpd/net_types.h +++ b/btpd/net_types.h @@ -63,6 +63,7 @@ struct peer { long t_created; long t_wantwrite; + long t_nointerest; struct { uint32_t msg_len; diff --git a/btpd/peer.c b/btpd/peer.c index 7ce486d..c8f60dc 100644 --- a/btpd/peer.c +++ b/btpd/peer.c @@ -250,6 +250,7 @@ peer_unwant(struct peer *p, uint32_t index) p->nwant--; if (p->nwant == 0) { p->flags &= ~PF_I_WANT; + p->t_nointerest = btpd_seconds; if (p->nreqs_out == 0) peer_send(p, nb_create_uninterest()); else @@ -265,6 +266,7 @@ peer_create_common(int sd) p->sd = sd; p->flags = PF_I_CHOKE | PF_P_CHOKE; p->t_created = btpd_seconds; + p->t_nointerest = btpd_seconds; BTPDQ_INIT(&p->my_reqs); BTPDQ_INIT(&p->outq); @@ -416,6 +418,7 @@ peer_on_uninterest(struct peer *p) return; else { p->flags &= ~PF_P_WANT; + p->t_nointerest = btpd_seconds; ul_on_uninterest(p); } } @@ -512,13 +515,23 @@ peer_on_cancel(struct peer *p, uint32_t index, uint32_t begin, void peer_on_tick(struct peer *p) { - if ((p->flags & PF_ATTACHED) == 0 && btpd_seconds - p->t_created >= 60) { - btpd_log(BTPD_L_CONN, "hand shake timed out.\n"); - peer_kill(p); - } else if (!BTPDQ_EMPTY(&p->outq) && btpd_seconds - p->t_wantwrite >= 60) { - btpd_log(BTPD_L_CONN, "write attempt timed out.\n"); - peer_kill(p); + if (p->flags & PF_ATTACHED) { + if (!BTPDQ_EMPTY(&p->outq) && btpd_seconds - p->t_wantwrite >= 60) { + btpd_log(BTPD_L_CONN, "write attempt timed out.\n"); + goto kill; + } + if ((cm_full(p->n->tp) && !(p->flags & PF_P_WANT) && + btpd_seconds - p->t_nointerest >= 600)) { + btpd_log(BTPD_L_CONN, "no interest for 10 minutes.\n"); + goto kill; + } + } else if (btpd_seconds - p->t_created >= 60) { + btpd_log(BTPD_L_CONN, "hand shake timed out.\n"); + goto kill; } + return; +kill: + peer_kill(p); } int