tSimplify state handling for peers - libeech - bittorrent library
(HTM) git clone git://z3bra.org/libeech.git
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
(DIR) commit 56d2950fcc3d48250a2eed27cbc2c551f83ee0ec
(DIR) parent b5d392cf923e35b7d2dee33ca323447b4004f270
(HTM) Author: z3bra <contactatz3bradotorg>
Date: Wed, 11 Jul 2018 08:48:50 +0200
Simplify state handling for peers
Diffstat:
M libeech.c | 71 ++++++++++++++++++++++++++++++-
1 file changed, 70 insertions(+), 1 deletion(-)
---
(DIR) diff --git a/libeech.c b/libeech.c
t@@ -79,6 +79,7 @@ static ssize_t pwptxst(struct peer *, int);
static ssize_t pwptxhv(struct peer *, long);
static ssize_t pwptxbf(struct torrent *, struct peer *);
static ssize_t pwptxrq(struct torrent *, struct peer *);
+static ssize_t pwptxcl(struct torrent *, struct peer *);
/* receive different PWP messages */
static int pwprxst(struct peer *, int);
t@@ -89,6 +90,7 @@ static int pwprxpc(struct torrent *, struct peer *, size_t, char *);
/* various wrappers around PWP messages */
static int catchup(struct torrent *, struct peer *);
+static int cancelrq(struct torrent *, struct peer *);
/* handle all received PWP messages */
static int pwprxcb(struct torrent *, struct peer *, int, size_t, char *);
t@@ -676,6 +678,55 @@ pwptxrq(struct torrent *t, struct peer *p)
return 0;
}
+static ssize_t
+pwptxcl(struct torrent *t, struct peer *p)
+{
+ char m[MSGSIZ];
+ ssize_t i, bl, bo;
+
+ /* We're not requesting anything from peer */
+ if (p->piece.n < 0)
+ return 0;
+
+ /* Find a block that hasn't been requested yet */
+ for (i = 0; i < BLKNUM && bit(p->piece.rq, i); i++) {
+
+ /* We currently don't have the requested block */
+ if (!bit(p->piece.bl, i))
+ continue;
+
+ bo = i * BLKSIZ;
+ bl = BLKSIZ;
+ if (bo + BLKSIZ > p->piece.sz)
+ bl = p->piece.sz - bo;
+
+ /* All blocks requested */
+ if (bo >= p->piece.sz)
+ return -1;
+
+ memset(m, 0, MSGSIZ);
+
+ /* Message length */
+ U32(m) = htonl(13);
+
+ /* Message type */
+ m[4] = CANCEL;
+
+ /* Piece index */
+ U32(m+5) = htonl(p->piece.n);
+
+ /* Block offset */
+ U32(m+9) = htonl(bo);
+
+ /* Block length */
+ U32(m+13) = htonl(bl);
+
+ pwpsend(p, m, 17);
+ }
+
+ return 0;
+}
+
/* Receive and treat a change of status from the peer */
static int
pwprxst(struct peer *p, int type)
t@@ -786,6 +837,18 @@ catchup(struct torrent *t, struct peer *p)
}
/*
+ * Sent CANCEL messages for all pieces still requested that we have
+ */
+static int
+cancelrq(struct torrent *t, struct peer *p)
+{
+ if (p->piece.n >= 0 && bit(t->bf, p->piece.n))
+ pwptxcl(t, p);
+
+ return 0;
+}
+
+/*
* PWP message received callback
* This function will run the appropriate function based on the message type
*/
t@@ -828,6 +891,9 @@ pwptx(struct torrent *t, struct peer *p)
p->state |= HANDSHAKESENT;
}
+ if (!(p->state & CONNECTED))
+ return 0;
+
if (p->state & LEECHING) {
if (!(p->state & AMINTERESTED)) {
pwptxst(p, INTERESTED);
t@@ -836,6 +902,9 @@ pwptx(struct torrent *t, struct peer *p)
if (!(p->state & AMCHOKING))
pwptxrq(t, p);
+
+ if (memcmp(p->piece.rq, p->piece.bl, PCENUM / 8 + !!(PCENUM % 8)))
+ cancelrq(t, p);
}
if (p->state & SEEDING) {
t@@ -944,7 +1013,7 @@ netloop(struct torrent *t, int timeout)
/* peer is now ready to exchange data */
if (pfds.p[i]->state == (HANDSHAKESENT|HANDSHAKERCVD))
- pfds.p[i]->state |= (CONNECTED|SEEDING|LEECHING|AMCHOKING);
+ pfds.p[i]->state |= (CONNECTED|LEECHING|AMCHOKING);
}
free(pfds.p);