diff --git a/btpd/net.c b/btpd/net.c
index 1c22111..ecd76e0 100644
--- a/btpd/net.c
+++ b/btpd/net.c
@@ -58,6 +58,18 @@ net_write_cb(int sd, short type, void *arg)
     }
 }
 
+void
+net_write32(void *buf, uint32_t num)
+{
+    *(uint32_t *)buf = htonl(num);
+}
+
+uint32_t
+net_read32(void *buf)
+{
+    return ntohl(*(uint32_t *)buf);
+}
+
 static void
 kill_buf_no(char *buf, size_t len)
 {
@@ -93,7 +105,7 @@ struct net_buf *
 nb_create_alloc(short type, size_t len)
 {
     struct net_buf *nb = btpd_calloc(1, sizeof(*nb) + len);
-    nb->info.type = type;
+    nb->type = type;
     nb->buf = (char *)(nb + 1);
     nb->len = len;
     nb->kill_buf = kill_buf_no;
@@ -105,13 +117,54 @@ nb_create_set(short type, char *buf, size_t len,
     void (*kill_buf)(char *, size_t))
 {
     struct net_buf *nb = btpd_calloc(1, sizeof(*nb));
-    nb->info.type = type;
+    nb->type = type;
     nb->buf = buf;
     nb->len = len;
     nb->kill_buf = kill_buf;
     return nb;
 }
 
+uint32_t
+nb_get_index(struct net_buf *nb)
+{
+    switch (nb->type) {
+    case NB_CANCEL:
+    case NB_HAVE:
+    case NB_PIECE:
+    case NB_REQUEST:
+	return net_read32(nb->buf + 5);
+    default:
+	abort();
+    }
+}
+
+uint32_t
+nb_get_begin(struct net_buf *nb)
+{
+    switch (nb->type) {
+    case NB_CANCEL:
+    case NB_PIECE:
+    case NB_REQUEST:
+	return net_read32(nb->buf + 9);
+    default:
+	abort();
+    }
+}
+
+uint32_t
+nb_get_length(struct net_buf *nb)
+{
+    switch (nb->type) {
+    case NB_CANCEL:
+    case NB_REQUEST:
+	return net_read32(nb->buf + 13);
+    case NB_PIECE:
+	return net_read32(nb->buf) - 9;
+    default:
+	abort();
+    }
+}
+
 void
 kill_shake(struct input_reader *reader)
 {
@@ -173,7 +226,7 @@ net_write(struct peer *p, unsigned long wmax)
     while (bcount > 0) {
 	unsigned long bufdelta = nl->nb->len - p->outq_off;
 	if (bcount >= bufdelta) {
-	    if (nl->nb->info.type == NB_TORRENTDATA) {
+	    if (nl->nb->type == NB_TORRENTDATA) {
 		p->tp->uploaded += bufdelta;
 		p->rate_from_me[btpd.seconds % RATEHISTORY] += bufdelta;
 	    }
@@ -184,7 +237,7 @@ net_write(struct peer *p, unsigned long wmax)
 	    p->outq_off = 0;
 	    nl = BTPDQ_FIRST(&p->outq);
 	} else {
-	    if (nl->nb->info.type == NB_TORRENTDATA) {
+	    if (nl->nb->type == NB_TORRENTDATA) {
 		p->tp->uploaded += bcount;
 		p->rate_from_me[btpd.seconds % RATEHISTORY] += bcount;
 	    }
@@ -243,18 +296,6 @@ net_unsend(struct peer *p, struct nb_link *nl)
 	return 0;
 }
 
-void
-net_write32(void *buf, uint32_t num)
-{
-    *(uint32_t *)buf = htonl(num);
-}
-
-uint32_t
-net_read32(void *buf)
-{
-    return ntohl(*(uint32_t *)buf);
-}
-
 void
 net_send_piece(struct peer *p, uint32_t index, uint32_t begin,
 	       char *block, size_t blen)
@@ -271,9 +312,6 @@ net_send_piece(struct peer *p, uint32_t index, uint32_t begin,
     net_send(p, head);
 
     piece = nb_create_set(NB_TORRENTDATA, block, blen, kill_buf_free);
-    piece->info.index = index;
-    piece->info.begin = begin;
-    piece->info.length = blen;
     net_send(p, piece);
 }
 
@@ -286,9 +324,6 @@ net_send_request(struct peer *p, struct piece_req *req)
     net_write32(out->buf + 5, req->index);
     net_write32(out->buf + 9, req->begin);
     net_write32(out->buf + 13, req->length);
-    out->info.index = req->index;
-    out->info.begin = req->begin;
-    out->info.length = req->length;
     net_send(p, out);
 }
 
@@ -301,9 +336,6 @@ net_send_cancel(struct peer *p, struct piece_req *req)
     net_write32(out->buf + 5, req->index);
     net_write32(out->buf + 9, req->begin);
     net_write32(out->buf + 13, req->length);
-    out->info.index = req->index;
-    out->info.begin = req->begin;
-    out->info.length = req->length;
     net_send(p, out);
 }
 
@@ -314,7 +346,6 @@ net_send_have(struct peer *p, uint32_t index)
     net_write32(out->buf, 5);
     out->buf[4] = MSG_HAVE;
     net_write32(out->buf + 5, index);
-    out->info.index = index;
     net_send(p, out);
 }
 
diff --git a/btpd/net.h b/btpd/net.h
index 048a19b..9fe7b30 100644
--- a/btpd/net.h
+++ b/btpd/net.h
@@ -26,13 +26,8 @@
 #define NB_SHAKE	13
 
 struct net_buf {
+    short type;
     unsigned refs;
-
-    struct {
-	short type;
-	uint32_t index, begin, length;
-    } info;
-
     char *buf;
     size_t len;
     void (*kill_buf)(char *, size_t);
@@ -50,6 +45,9 @@ struct net_buf *nb_create_set(short type, char *buf, size_t len,
     void (*kill_buf)(char *, size_t));
 int nb_drop(struct net_buf *nb);
 void nb_hold(struct net_buf *nb);
+uint32_t nb_get_index(struct net_buf *nb);
+uint32_t nb_get_begin(struct net_buf *nb);
+uint32_t nb_get_length(struct net_buf *nb);
 
 struct peer;
 
diff --git a/btpd/peer.c b/btpd/peer.c
index a8058a6..7126bdc 100644
--- a/btpd/peer.c
+++ b/btpd/peer.c
@@ -62,6 +62,8 @@ peer_kill(struct peer *p)
 void
 peer_request(struct peer *p, uint32_t index, uint32_t begin, uint32_t len)
 {
+    if (p->tp->endgame == 0)
+	assert(p->nreqs_out < MAXPIPEDREQUESTS);
     p->nreqs_out++;
     struct piece_req *req = btpd_calloc(1, sizeof(*req));
     req->index = index;
@@ -76,12 +78,9 @@ peer_cancel(struct peer *p, uint32_t index, uint32_t begin, uint32_t len)
 {
     struct piece_req *req;
 again:
-    req = BTPDQ_FIRST(&p->my_reqs);
-    while (req != NULL &&
-	   !(index == req->index &&
-	     begin == req->begin &&
-	     len == req->length))
-	req = BTPDQ_NEXT(req, entry);
+    BTPDQ_FOREACH(req, &p->my_reqs, entry)
+	if (index == req->index && begin == req->begin && len == req->length)
+	    break;
     if (req != NULL) {
 	net_send_cancel(p, req);
 	BTPDQ_REMOVE(&p->my_reqs, req, entry);
@@ -110,7 +109,7 @@ peer_choke(struct peer *p)
     struct nb_link *nl = BTPDQ_FIRST(&p->outq);
     while (nl != NULL) {
 	struct nb_link *next = BTPDQ_NEXT(nl, entry);
-	if (nl->nb->info.type == NB_PIECE) {
+	if (nl->nb->type == NB_PIECE) {
 	    struct nb_link *data = next;
 	    next = BTPDQ_NEXT(next, entry);
 	    if (net_unsend(p, nl))
@@ -306,10 +305,10 @@ peer_on_cancel(struct peer *p, uint32_t index, uint32_t begin,
 {
     struct nb_link *nl;
     BTPDQ_FOREACH(nl, &p->outq, entry)
-	if (nl->nb->info.type == NB_PIECE
-	    && nl->nb->info.index == index
-	    && nl->nb->info.begin == begin
-	    && nl->nb->info.length == length) {
+	if (nl->nb->type == NB_PIECE
+	    && nb_get_begin(nl->nb) == begin
+	    && nb_get_index(nl->nb) == index
+	    && nb_get_length(nl->nb) == length) {
 	    struct nb_link *data = BTPDQ_NEXT(nl, entry);
 	    if (net_unsend(p, nl))
 		net_unsend(p, data);