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 */