libeech

BitTorrent library
git clone git://z3bra.org/libeech.git
Log | Files | Refs | README | LICENSE

commit 56d2950fcc3d48250a2eed27cbc2c551f83ee0ec
parent b5d392cf923e35b7d2dee33ca323447b4004f270
Author: z3bra <contactatz3bradotorg>
Date:   Wed, 11 Jul 2018 08:48:50 +0200

Simplify state handling for peers

Diffstat:
libeech.c | 71++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 70 insertions(+), 1 deletion(-)

diff --git a/libeech.c b/libeech.c @@ -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); @@ -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 *); @@ -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) @@ -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 */ @@ -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); @@ -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) { @@ -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);