Strangely such connections are not entirely uncommon. Added a hand shake time out of 60 seconds to resolve this. Added a peer_on_tick function which is used to monitor peers for different timeouts. Timestamps are compared against the reborn btpd_seconds. The issue has been reported by Ludvig Omholt and Arnaud Bergeron.master
@@ -32,8 +32,11 @@ | |||
static uint8_t m_peer_id[20]; | |||
static struct event m_sigint; | |||
static struct event m_sigterm; | |||
static struct event m_heartbeat; | |||
static int m_shutdown; | |||
long btpd_seconds; | |||
void | |||
btpd_exit(int code) | |||
{ | |||
@@ -92,6 +95,14 @@ signal_cb(int signal, short type, void *arg) | |||
btpd_shutdown(30); | |||
} | |||
static void | |||
heartbeat_cb(int fd, short type, void *arg) | |||
{ | |||
btpd_ev_add(&m_heartbeat, (& (struct timeval) { 1, 0 })); | |||
btpd_seconds++; | |||
net_on_tick(); | |||
} | |||
struct td_cb { | |||
void (*cb)(void *); | |||
void *arg; | |||
@@ -196,4 +207,6 @@ btpd_init(void) | |||
btpd_ev_add(&m_sigint, NULL); | |||
signal_set(&m_sigterm, SIGTERM, signal_cb, NULL); | |||
btpd_ev_add(&m_sigterm, NULL); | |||
evtimer_set(&m_heartbeat, heartbeat_cb, NULL); | |||
btpd_ev_add(&m_heartbeat, (& (struct timeval) { 1, 0 })); | |||
} |
@@ -39,6 +39,8 @@ | |||
#define BTPD_L_BTPD 0x00000010 | |||
#define BTPD_L_POL 0x00000020 | |||
extern long btpd_seconds; | |||
void btpd_init(void); | |||
void btpd_log(uint32_t type, const char *fmt, ...); | |||
@@ -18,7 +18,6 @@ | |||
#include "btpd.h" | |||
static struct event m_bw_timer; | |||
static unsigned long m_bw_bytes_in; | |||
static unsigned long m_bw_bytes_out; | |||
@@ -178,7 +177,8 @@ net_write(struct peer *p, unsigned long wmax) | |||
nwritten = writev(p->sd, iov, niov); | |||
if (nwritten < 0) { | |||
if (errno == EAGAIN) { | |||
btpd_ev_add(&p->out_ev, WRITE_TIMEOUT); | |||
btpd_ev_add(&p->out_ev, NULL); | |||
p->t_wantwrite = btpd_seconds; | |||
return 0; | |||
} else { | |||
btpd_log(BTPD_L_CONN, "write error: %s\n", strerror(errno)); | |||
@@ -217,8 +217,10 @@ net_write(struct peer *p, unsigned long wmax) | |||
bcount = 0; | |||
} | |||
} | |||
if (!BTPDQ_EMPTY(&p->outq)) | |||
btpd_ev_add(&p->out_ev, WRITE_TIMEOUT); | |||
if (!BTPDQ_EMPTY(&p->outq)) { | |||
btpd_ev_add(&p->out_ev, NULL); | |||
p->t_wantwrite = btpd_seconds; | |||
} | |||
return nwritten; | |||
} | |||
@@ -570,15 +572,11 @@ compute_rates(void) { | |||
m_rate_dwn += tot_dwn - compute_rate_sub(m_rate_dwn); | |||
} | |||
void | |||
net_bw_cb(int sd, short type, void *arg) | |||
static void | |||
net_bw_tick(void) | |||
{ | |||
struct peer *p; | |||
btpd_ev_add(&m_bw_timer, (& (struct timeval) { 1, 0 })); | |||
compute_rates(); | |||
m_bw_bytes_out = net_bw_limit_out; | |||
m_bw_bytes_in = net_bw_limit_in; | |||
@@ -597,7 +595,8 @@ net_bw_cb(int sd, short type, void *arg) | |||
} | |||
if (net_bw_limit_out) { | |||
while ((p = BTPDQ_FIRST(&net_bw_writeq)) != NULL && m_bw_bytes_out > 0) { | |||
while (((p = BTPDQ_FIRST(&net_bw_writeq)) != NULL | |||
&& m_bw_bytes_out > 0)) { | |||
BTPDQ_REMOVE(&net_bw_writeq, p, wq_entry); | |||
p->flags &= ~PF_ON_WRITEQ; | |||
m_bw_bytes_out -= net_write(p, m_bw_bytes_out); | |||
@@ -611,6 +610,28 @@ net_bw_cb(int sd, short type, void *arg) | |||
} | |||
} | |||
static void | |||
run_peer_ticks(void) | |||
{ | |||
struct net *n; | |||
struct peer *p, *next; | |||
BTPDQ_FOREACH_MUTABLE(p, &net_unattached, p_entry, next) | |||
peer_on_tick(p); | |||
BTPDQ_FOREACH(n, &m_torrents, entry) | |||
BTPDQ_FOREACH_MUTABLE(p, &n->peers, p_entry, next) | |||
peer_on_tick(p); | |||
} | |||
void | |||
net_on_tick(void) | |||
{ | |||
run_peer_ticks(); | |||
compute_rates(); | |||
net_bw_tick(); | |||
} | |||
void | |||
net_read_cb(int sd, short type, void *arg) | |||
{ | |||
@@ -629,16 +650,11 @@ void | |||
net_write_cb(int sd, short type, void *arg) | |||
{ | |||
struct peer *p = (struct peer *)arg; | |||
if (type == EV_TIMEOUT) { | |||
btpd_log(BTPD_L_CONN, "Write attempt timed out.\n"); | |||
peer_kill(p); | |||
return; | |||
} | |||
if (net_bw_limit_out == 0) { | |||
if (net_bw_limit_out == 0) | |||
net_write(p, 0); | |||
} else if (m_bw_bytes_out > 0) { | |||
else if (m_bw_bytes_out > 0) | |||
m_bw_bytes_out -= net_write(p, m_bw_bytes_out); | |||
} else { | |||
else { | |||
p->flags |= PF_ON_WRITEQ; | |||
BTPDQ_INSERT_TAIL(&net_bw_writeq, p, wq_entry); | |||
} | |||
@@ -672,7 +688,4 @@ net_init(void) | |||
event_set(&m_net_incoming, sd, EV_READ | EV_PERSIST, | |||
net_connection_cb, NULL); | |||
btpd_ev_add(&m_net_incoming, NULL); | |||
evtimer_set(&m_bw_timer, net_bw_cb, NULL); | |||
btpd_ev_add(&m_bw_timer, (& (struct timeval) { 1, 0 })); | |||
} |
@@ -11,8 +11,6 @@ | |||
#define MSG_PIECE 7 | |||
#define MSG_CANCEL 8 | |||
#define WRITE_TIMEOUT (& (struct timeval) { 60, 0 }) | |||
extern struct peer_tq net_unattached; | |||
extern struct peer_tq net_bw_readq; | |||
extern struct peer_tq net_bw_writeq; | |||
@@ -20,6 +18,8 @@ extern unsigned net_npeers; | |||
void net_init(void); | |||
void net_on_tick(void); | |||
void net_create(struct torrent *tp); | |||
void net_kill(struct torrent *tp); | |||
@@ -61,6 +61,9 @@ struct peer { | |||
unsigned long rate_up, rate_dwn; | |||
unsigned long count_up, count_dwn; | |||
long t_created; | |||
long t_wantwrite; | |||
struct { | |||
uint32_t msg_len; | |||
uint8_t msg_num; | |||
@@ -66,7 +66,8 @@ peer_send(struct peer *p, struct net_buf *nb) | |||
if (BTPDQ_EMPTY(&p->outq)) { | |||
assert(p->outq_off == 0); | |||
btpd_ev_add(&p->out_ev, WRITE_TIMEOUT); | |||
btpd_ev_add(&p->out_ev, NULL); | |||
p->t_wantwrite = btpd_seconds; | |||
} | |||
BTPDQ_INSERT_TAIL(&p->outq, nl, entry); | |||
} | |||
@@ -263,6 +264,7 @@ peer_create_common(int sd) | |||
p->sd = sd; | |||
p->flags = PF_I_CHOKE | PF_P_CHOKE; | |||
p->t_created = btpd_seconds; | |||
BTPDQ_INIT(&p->my_reqs); | |||
BTPDQ_INIT(&p->outq); | |||
@@ -507,6 +509,18 @@ peer_on_cancel(struct peer *p, uint32_t index, uint32_t begin, | |||
} | |||
} | |||
void | |||
peer_on_tick(struct peer *p) | |||
{ | |||
if ((p->flags & PF_ATTACHED) == 0 && btpd_seconds - p->t_created >= 60) { | |||
btpd_log(BTPD_L_CONN, "hand shake timed out.\n"); | |||
peer_kill(p); | |||
} else if (!BTPDQ_EMPTY(&p->outq) && btpd_seconds - p->t_wantwrite >= 60) { | |||
btpd_log(BTPD_L_CONN, "write attempt timed out.\n"); | |||
peer_kill(p); | |||
} | |||
} | |||
int | |||
peer_chokes(struct peer *p) | |||
{ | |||
@@ -52,6 +52,7 @@ void peer_on_request(struct peer *p, uint32_t index, uint32_t begin, | |||
uint32_t length); | |||
void peer_on_cancel(struct peer *p, uint32_t index, uint32_t begin, | |||
uint32_t length); | |||
void peer_on_tick(struct peer *p); | |||
int peer_active_down(struct peer *p); | |||
int peer_active_up(struct peer *p); | |||