tTreat HANDSHAKE as any other PWP message - libeech - bittorrent library
 (HTM) git clone git://z3bra.org/libeech.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit c849aac19002f74d44d63ad8350f00601325afd3
 (DIR) parent e158a4f97b00d3b99b9d2d11a40af07db9883858
 (HTM) Author: Willy Goiffon <dev@z3bra.org>
       Date:   Mon, 23 Mar 2020 20:13:29 +0100
       
       Treat HANDSHAKE as any other PWP message
       
       Diffstat:
         M libeech.c                           |      64 ++++++++++++++++++++-----------
       
       1 file changed, 41 insertions(+), 23 deletions(-)
       ---
 (DIR) diff --git a/libeech.c b/libeech.c
       t@@ -35,7 +35,8 @@ enum {
                BITFIELD,
                REQUEST,
                PIECE,
       -        CANCEL
       +        CANCEL,
       +        HANDSHAKE
        };
        
        struct peerfds {
       t@@ -69,8 +70,9 @@ static int peercnt(struct peer *);
        static ssize_t pwprecv(struct peer *);
        static ssize_t pwpsend(struct peer *, char *, size_t);
        
       -/* send, receive and verify handshakes */
       -static int pwphsck(struct torrent *, char *, long);
       +/* receive and verify handshakes */
       +static ssize_t hsrecv(struct peer *);
       +static int hsck(struct torrent *, char *, long);
        
        /* send different PWP messages */
        static ssize_t send_handshake(struct torrent *, struct peer *);
       t@@ -81,12 +83,12 @@ static ssize_t send_request(struct torrent *, struct peer *);
        static ssize_t send_cancel(struct torrent *, struct peer *);
        
        /* callbacks for received PWP messages */
       -static ssize_t cb_handshake(struct peer *);
        static int cb_state(struct peer *, int);
        static int cb_have(struct peer *, size_t, char *);
        static int cb_bitfield(struct peer *, size_t, char *);
        static int cb_request(struct torrent *, struct peer *, size_t, char *);
        static int cb_piece(struct torrent *, struct peer *, size_t, char *);
       +static int cb_handshake(struct torrent *, struct peer *);
        
        /* various wrappers around PWP messages */
        static int catchup(struct torrent *, struct peer *);
       t@@ -427,7 +429,6 @@ pwprecv(struct peer *p)
                ssize_t l, r;
        
                if (!p->rxbufsz) {
       -                memset(p->rxbuf, 0, MSGSIZ);
                        /* read the first 4 bytes to get message length */
                        if ((r = recv(p->fd, p->rxbuf, 4, MSG_PEEK)) < 4)
                                return -1;
       t@@ -504,22 +505,25 @@ send_handshake(struct torrent *t, struct peer *p)
         * We cannot receive it as a standard PWP message.
         */
        static ssize_t
       -cb_handshake(struct peer *p)
       +hsrecv(struct peer *p)
        {
       -        ssize_t r;
       +        ssize_t l, r;
        
       -        while ((r = recv(p->fd, p->rxbuf, 68 - p->rxbufsz, 0)) > 0)
       +        /* expected handshake length */
       +        l = 68;
       +
       +        while ((r = recv(p->fd, p->rxbuf + p->rxbufsz, l - p->rxbufsz, 0)) > 0)
                        p->rxbufsz += r;
        
       -        if (r < 0)
       +        if (r < 0 && errno != EAGAIN)
                        return -1;
        
       -        return p->rxbufsz;
       +        return l - p->rxbufsz;
        }
        
        /* Verify that a handshake is valid according to a torrent */
        static int
       -pwphsck(struct torrent *t, char *hs, long l)
       +hsck(struct torrent *t, char *hs, long l)
        {
                if (l != 68)
                        return -1;
       t@@ -819,6 +823,18 @@ cb_piece(struct torrent *t, struct peer *p, size_t sz, char *pl)
                return 0;
        }
        
       +int
       +cb_handshake(struct torrent *t, struct peer *p)
       +{
       +        if (hsck(t, p->rxbuf, p->rxbufsz) < 0) {
       +                delpeer(t->peers, p);
       +                return -1;
       +        }
       +
       +        p->state |= HANDSHAKERCVD;
       +        return 0;
       +}
       +
        /*
         * Get a peer to catch up new pieces we had received
         */
       t@@ -877,6 +893,9 @@ callbacks(struct torrent *t, struct peer *p, int type, size_t sz, char *pl)
                        case CANCEL:
                                /* not handled */
                                break;
       +                case HANDSHAKE:
       +                        cb_handshake(t, p);
       +                        break;
                }
                return 0;
        }
       t@@ -925,22 +944,21 @@ pwptx(struct torrent *t, struct peer *p)
        static int
        pwprx(struct torrent *t, struct peer *p)
        {
       -        /* receive and verify handshake */
       -        if (!(p->state & HANDSHAKERCVD)) {
       -                cb_handshake(p);
       -                if (p->rxbufsz >= 68 && pwphsck(t, p->rxbuf, p->rxbufsz)) {
       -                        delpeer(t->peers, p);
       -                        return -1;
       -                }
       -                p->rxbufsz = 0;
       -                p->state |= HANDSHAKERCVD;
       -        } else if (!pwprecv(p)) {
       -                callbacks(t, p, p->rxbuf[4], p->rxbufsz - 5, p->rxbuf+5);
       +        int type;
       +        ssize_t r;
       +
       +        /* First message from peer should be the handshake */
       +        r = (p->state & HANDSHAKERCVD) ? pwprecv(p) : hsrecv(p);
       +
       +        if (!r) {
       +                type  = (p->state & HANDSHAKERCVD) ? p->rxbuf[4] : HANDSHAKE;
       +                callbacks(t, p, type, p->rxbufsz - 5, p->rxbuf+5);
                        memset(p->rxbuf, 0, MSGSIZ);
                        p->rxbufsz = 0;
       +                return 0;
                }
        
       -        return 0;
       +        return -1;
        }
        
        /* Initiate connection with a peer */