diff --git a/btpd/download.c b/btpd/download.c
index 94855bf..fd7f680 100644
--- a/btpd/download.c
+++ b/btpd/download.c
@@ -12,20 +12,9 @@ dl_start(struct torrent *tp)
 void
 dl_stop(struct torrent *tp)
 {
-    struct peer *peer;
-    struct piece *piece;
-
-    peer = BTPDQ_FIRST(&tp->peers);
-    while (peer != NULL) {
-        struct peer *next = BTPDQ_NEXT(peer, p_entry);
-        BTPDQ_REMOVE(&tp->peers, peer, p_entry);
-        BTPDQ_INSERT_TAIL(&net_unattached, peer, p_entry);
-        peer->flags &= ~PF_ATTACHED;
-        peer = next;
-    }
-
-    while ((piece = BTPDQ_FIRST(&tp->getlst)) != NULL)
-        piece_free(piece);
+    struct piece *pc;
+    while ((pc = BTPDQ_FIRST(&tp->getlst)) != NULL)
+        piece_free(pc);
 }
 
 /*
@@ -165,11 +154,6 @@ dl_on_bad_piece(struct piece *pc)
 void
 dl_on_new_peer(struct peer *p)
 {
-    struct torrent *tp = p->tp;
-    tp->npeers++;
-    p->flags |= PF_ATTACHED;
-    BTPDQ_REMOVE(&net_unattached, p, p_entry);
-    BTPDQ_INSERT_HEAD(&tp->peers, p, p_entry);
 }
 
 void
@@ -177,26 +161,12 @@ dl_on_lost_peer(struct peer *p)
 {
     struct torrent *tp = p->tp;
 
-    assert(tp->npeers > 0 && (p->flags & PF_ATTACHED) != 0);
-    tp->npeers--;
-    p->flags &= ~PF_ATTACHED;
-    BTPDQ_REMOVE(&tp->peers, p, p_entry);
-
     for (uint32_t i = 0; i < tp->meta.npieces; i++)
         if (peer_has(p, i))
             tp->piece_count[i]--;
 
     if (p->nreqs_out > 0)
         dl_on_undownload(p);
-#if 0
-    struct piece *pc = BTPDQ_FIRST(&tp->getlst);
-    while (pc != NULL) {
-        struct piece *next = BTPDQ_NEXT(pc, entry);
-        if (peer_has(p, pc->index) && tp->piece_count[pc->index] == 0)
-            dl_on_peerless_piece(pc);
-        pc = next;
-    }
-#endif
 }
 
 void
diff --git a/btpd/net.c b/btpd/net.c
index 0c74cb7..ea3c2a5 100644
--- a/btpd/net.c
+++ b/btpd/net.c
@@ -41,6 +41,7 @@ struct peer_tq net_unattached = BTPDQ_HEAD_INITIALIZER(net_unattached);
 void
 net_add_torrent(struct torrent *tp)
 {
+    tp->net_active = 1;
     BTPDQ_INSERT_HEAD(&m_torrents, tp, net_entry);
     m_ntorrents++;
     dl_start(tp);
@@ -49,6 +50,7 @@ net_add_torrent(struct torrent *tp)
 void
 net_del_torrent(struct torrent *tp)
 {
+    tp->net_active = 0;
     assert(m_ntorrents > 0);
     m_ntorrents--;
     BTPDQ_REMOVE(&m_torrents, tp, net_entry);
@@ -63,6 +65,13 @@ net_del_torrent(struct torrent *tp)
             peer_kill(p);
         p = next;
     }
+
+    p = BTPDQ_FIRST(&tp->peers);
+    while (p != NULL) {
+        struct peer *next = BTPDQ_NEXT(p, p_entry);
+        peer_kill(p);
+        p = next;
+    }
 }
 
 void
diff --git a/btpd/peer.c b/btpd/peer.c
index 87cdf5e..c7273ff 100644
--- a/btpd/peer.c
+++ b/btpd/peer.c
@@ -17,8 +17,12 @@ peer_kill(struct peer *p)
     btpd_log(BTPD_L_CONN, "killed peer %p\n", p);
 
     if (p->flags & PF_ATTACHED) {
-        ul_on_lost_peer(p);
-        dl_on_lost_peer(p);
+        if (p->tp->net_active) {
+            ul_on_lost_peer(p);
+            dl_on_lost_peer(p);
+        }
+        BTPDQ_REMOVE(&p->tp->peers, p, p_entry);
+        p->tp->npeers--;
     } else
         BTPDQ_REMOVE(&net_unattached, p, p_entry);
     if (p->flags & PF_ON_READQ)
@@ -340,6 +344,12 @@ peer_on_shake(struct peer *p)
             peer_send(p, nb_create_bitdata(p->tp));
         }
     }
+
+    BTPDQ_REMOVE(&net_unattached, p, p_entry);
+    BTPDQ_INSERT_HEAD(&p->tp->peers, p, p_entry);
+    p->flags |= PF_ATTACHED;
+    p->tp->npeers++;
+
     ul_on_new_peer(p);
     dl_on_new_peer(p);
 }
diff --git a/btpd/torrent.h b/btpd/torrent.h
index fbfc296..cb3be8e 100644
--- a/btpd/torrent.h
+++ b/btpd/torrent.h
@@ -41,6 +41,8 @@ struct torrent {
     void *imem;
     size_t isiz;
 
+    int net_active;
+
     uint8_t *piece_field;
     uint8_t *block_field;