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);