@@ -221,6 +221,7 @@ net_write(struct peer *p, unsigned long wmax) | |||||
btpd_ev_add(&p->out_ev, NULL); | btpd_ev_add(&p->out_ev, NULL); | ||||
p->t_wantwrite = btpd_seconds; | p->t_wantwrite = btpd_seconds; | ||||
} | } | ||||
p->t_lastwrite = btpd_seconds; | |||||
return nwritten; | return nwritten; | ||||
} | } | ||||
@@ -7,6 +7,7 @@ static struct net_buf *m_choke; | |||||
static struct net_buf *m_unchoke; | static struct net_buf *m_unchoke; | ||||
static struct net_buf *m_interest; | static struct net_buf *m_interest; | ||||
static struct net_buf *m_uninterest; | static struct net_buf *m_uninterest; | ||||
static struct net_buf *m_keepalive; | |||||
static void | static void | ||||
kill_buf_no(char *buf, size_t len) | kill_buf_no(char *buf, size_t len) | ||||
@@ -57,13 +58,25 @@ nb_create_onesized(char mtype, int btype) | |||||
return out; | return out; | ||||
} | } | ||||
static struct net_buf *nb_singleton(struct net_buf *nb) | |||||
static struct net_buf * | |||||
nb_singleton(struct net_buf *nb) | |||||
{ | { | ||||
nb_hold(nb); | nb_hold(nb); | ||||
nb->kill_buf = kill_buf_abort; | nb->kill_buf = kill_buf_abort; | ||||
return nb; | return nb; | ||||
} | } | ||||
struct net_buf * | |||||
nb_create_keepalive(void) | |||||
{ | |||||
if (m_keepalive == NULL) { | |||||
m_keepalive = nb_create_alloc(NB_KEEPALIVE, 4); | |||||
net_write32(m_keepalive->buf, 0); | |||||
nb_singleton(m_keepalive); | |||||
} | |||||
return m_keepalive; | |||||
} | |||||
struct net_buf * | struct net_buf * | ||||
nb_create_piece(uint32_t index, uint32_t begin, size_t blen) | nb_create_piece(uint32_t index, uint32_t begin, size_t blen) | ||||
{ | { | ||||
@@ -14,6 +14,7 @@ | |||||
#define NB_MULTIHAVE 11 | #define NB_MULTIHAVE 11 | ||||
#define NB_BITDATA 12 | #define NB_BITDATA 12 | ||||
#define NB_SHAKE 13 | #define NB_SHAKE 13 | ||||
#define NB_KEEPALIVE 14 | |||||
struct net_buf { | struct net_buf { | ||||
short type; | short type; | ||||
@@ -33,6 +34,7 @@ BTPDQ_HEAD(nb_tq, nb_link); | |||||
struct torrent; | struct torrent; | ||||
struct peer; | struct peer; | ||||
struct net_buf *nb_create_keepalive(void); | |||||
struct net_buf *nb_create_piece(uint32_t index, uint32_t begin, size_t blen); | struct net_buf *nb_create_piece(uint32_t index, uint32_t begin, size_t blen); | ||||
struct net_buf *nb_create_torrentdata(char *block, size_t blen); | struct net_buf *nb_create_torrentdata(char *block, size_t blen); | ||||
struct net_buf *nb_create_request(uint32_t index, | struct net_buf *nb_create_request(uint32_t index, | ||||
@@ -62,6 +62,7 @@ struct peer { | |||||
unsigned long count_up, count_dwn; | unsigned long count_up, count_dwn; | ||||
long t_created; | long t_created; | ||||
long t_lastwrite; | |||||
long t_wantwrite; | long t_wantwrite; | ||||
long t_nointerest; | long t_nointerest; | ||||
@@ -106,6 +106,9 @@ void | |||||
peer_sent(struct peer *p, struct net_buf *nb) | peer_sent(struct peer *p, struct net_buf *nb) | ||||
{ | { | ||||
switch (nb->type) { | switch (nb->type) { | ||||
case NB_KEEPALIVE: | |||||
btpd_log(BTPD_L_MSG, "sent keepalive to %p\n", p); | |||||
break; | |||||
case NB_CHOKE: | case NB_CHOKE: | ||||
btpd_log(BTPD_L_MSG, "sent choke to %p\n", p); | btpd_log(BTPD_L_MSG, "sent choke to %p\n", p); | ||||
break; | break; | ||||
@@ -175,6 +178,12 @@ peer_requested(struct peer *p, uint32_t piece, uint32_t block) | |||||
return 0; | return 0; | ||||
} | } | ||||
void | |||||
peer_keepalive(struct peer *p) | |||||
{ | |||||
peer_send(p, nb_create_keepalive()); | |||||
} | |||||
void | void | ||||
peer_cancel(struct peer *p, struct block_request *req, struct net_buf *nb) | peer_cancel(struct peer *p, struct block_request *req, struct net_buf *nb) | ||||
{ | { | ||||
@@ -266,6 +275,7 @@ peer_create_common(int sd) | |||||
p->sd = sd; | p->sd = sd; | ||||
p->flags = PF_I_CHOKE | PF_P_CHOKE; | p->flags = PF_I_CHOKE | PF_P_CHOKE; | ||||
p->t_created = btpd_seconds; | p->t_created = btpd_seconds; | ||||
p->t_lastwrite = btpd_seconds; | |||||
p->t_nointerest = btpd_seconds; | p->t_nointerest = btpd_seconds; | ||||
BTPDQ_INIT(&p->my_reqs); | BTPDQ_INIT(&p->my_reqs); | ||||
BTPDQ_INIT(&p->outq); | BTPDQ_INIT(&p->outq); | ||||
@@ -516,7 +526,10 @@ void | |||||
peer_on_tick(struct peer *p) | peer_on_tick(struct peer *p) | ||||
{ | { | ||||
if (p->flags & PF_ATTACHED) { | if (p->flags & PF_ATTACHED) { | ||||
if (!BTPDQ_EMPTY(&p->outq) && btpd_seconds - p->t_wantwrite >= 60) { | |||||
if (BTPDQ_EMPTY(&p->outq)) { | |||||
if (btpd_seconds - p->t_lastwrite >= 120) | |||||
peer_keepalive(p); | |||||
} else if (btpd_seconds - p->t_wantwrite >= 60) { | |||||
btpd_log(BTPD_L_CONN, "write attempt timed out.\n"); | btpd_log(BTPD_L_CONN, "write attempt timed out.\n"); | ||||
goto kill; | goto kill; | ||||
} | } | ||||
@@ -21,6 +21,7 @@ void peer_send(struct peer *p, struct net_buf *nb); | |||||
int peer_unsend(struct peer *p, struct nb_link *nl); | int peer_unsend(struct peer *p, struct nb_link *nl); | ||||
void peer_sent(struct peer *p, struct net_buf *nb); | void peer_sent(struct peer *p, struct net_buf *nb); | ||||
void peer_keepalive(struct peer *p); | |||||
void peer_unchoke(struct peer *p); | void peer_unchoke(struct peer *p); | ||||
void peer_choke(struct peer *p); | void peer_choke(struct peer *p); | ||||
void peer_unwant(struct peer *p, uint32_t index); | void peer_unwant(struct peer *p, uint32_t index); | ||||