* Add function net_unsend to safely remove network buffers from a peer's outq. Use it where needed in peer.c.master
@@ -97,7 +97,6 @@ nb_create_alloc(short type, size_t len) | |||||
nb->buf = (char *)(nb + 1); | nb->buf = (char *)(nb + 1); | ||||
nb->len = len; | nb->len = len; | ||||
nb->kill_buf = kill_buf_no; | nb->kill_buf = kill_buf_no; | ||||
nb_hold(nb); | |||||
return nb; | return nb; | ||||
} | } | ||||
@@ -110,7 +109,6 @@ nb_create_set(short type, char *buf, size_t len, | |||||
nb->buf = buf; | nb->buf = buf; | ||||
nb->len = len; | nb->len = len; | ||||
nb->kill_buf = kill_buf; | nb->kill_buf = kill_buf; | ||||
nb_hold(nb); | |||||
return nb; | return nb; | ||||
} | } | ||||
@@ -209,6 +207,7 @@ net_send(struct peer *p, struct net_buf *nb) | |||||
{ | { | ||||
struct nb_link *nl = btpd_calloc(1, sizeof(*nl)); | struct nb_link *nl = btpd_calloc(1, sizeof(*nl)); | ||||
nl->nb = nb; | nl->nb = nb; | ||||
nb_hold(nb); | |||||
if (BTPDQ_EMPTY(&p->outq)) { | if (BTPDQ_EMPTY(&p->outq)) { | ||||
assert(p->outq_off == 0); | assert(p->outq_off == 0); | ||||
@@ -217,6 +216,33 @@ net_send(struct peer *p, struct net_buf *nb) | |||||
BTPDQ_INSERT_TAIL(&p->outq, nl, entry); | BTPDQ_INSERT_TAIL(&p->outq, nl, entry); | ||||
} | } | ||||
/* | |||||
* Remove a network buffer from the peer's outq. | |||||
* If a part of the buffer already have been written | |||||
* to the network it cannot be removed. | |||||
* | |||||
* Returns 1 if the buffer is removed, 0 if not. | |||||
*/ | |||||
int | |||||
net_unsend(struct peer *p, struct nb_link *nl) | |||||
{ | |||||
if (!(nl == BTPDQ_FIRST(&p->outq) && p->outq_off > 0)) { | |||||
BTPDQ_REMOVE(&p->outq, nl, entry); | |||||
nb_drop(nl->nb); | |||||
free(nl); | |||||
if (BTPDQ_EMPTY(&p->outq)) { | |||||
if (p->flags & PF_ON_WRITEQ) { | |||||
BTPDQ_REMOVE(&btpd.writeq, p, wq_entry); | |||||
p->flags &= ~PF_ON_WRITEQ; | |||||
} else | |||||
event_del(&p->out_ev); | |||||
} | |||||
return 1; | |||||
} else | |||||
return 0; | |||||
} | |||||
void | void | ||||
net_write32(void *buf, uint32_t num) | net_write32(void *buf, uint32_t num) | ||||
{ | { | ||||
@@ -120,7 +120,7 @@ void net_send_request(struct peer *p, struct piece_req *req); | |||||
void net_send_piece(struct peer *p, uint32_t index, uint32_t begin, | void net_send_piece(struct peer *p, uint32_t index, uint32_t begin, | ||||
char *block, size_t blen); | char *block, size_t blen); | ||||
void net_send_cancel(struct peer *p, struct piece_req *req); | void net_send_cancel(struct peer *p, struct piece_req *req); | ||||
int net_unsend(struct peer *p, struct nb_link *nl); | |||||
void net_handshake(struct peer *p, int incoming); | void net_handshake(struct peer *p, int incoming); | ||||
void net_read_cb(int sd, short type, void *arg); | void net_read_cb(int sd, short type, void *arg); | ||||
@@ -110,16 +110,11 @@ peer_choke(struct peer *p) | |||||
struct nb_link *nl = BTPDQ_FIRST(&p->outq); | struct nb_link *nl = BTPDQ_FIRST(&p->outq); | ||||
while (nl != NULL) { | while (nl != NULL) { | ||||
struct nb_link *next = BTPDQ_NEXT(nl, entry); | struct nb_link *next = BTPDQ_NEXT(nl, entry); | ||||
if (nl->nb->info.type == NB_PIECE | if (nl->nb->info.type == NB_PIECE) { | ||||
&& (nl != BTPDQ_FIRST(&p->outq) && p->outq_off > 0)) { | struct nb_link *data = next; | ||||
nb_drop(nl->nb); | |||||
BTPDQ_REMOVE(&p->outq, nl, entry); | |||||
free(nl); | |||||
nl = next; | |||||
next = BTPDQ_NEXT(next, entry); | next = BTPDQ_NEXT(next, entry); | ||||
nb_drop(nl->nb); | if (net_unsend(p, nl)) | ||||
BTPDQ_REMOVE(&p->outq, nl, entry); | net_unsend(p, data); | ||||
free(nl); | |||||
} | } | ||||
nl = next; | nl = next; | ||||
} | } | ||||
@@ -309,34 +304,17 @@ void | |||||
peer_on_cancel(struct peer *p, uint32_t index, uint32_t begin, | peer_on_cancel(struct peer *p, uint32_t index, uint32_t begin, | ||||
uint32_t length) | uint32_t length) | ||||
{ | { | ||||
struct nb_link *nl = BTPDQ_FIRST(&p->outq); | struct nb_link *nl; | ||||
if (nl == NULL) | BTPDQ_FOREACH(nl, &p->outq, entry) | ||||
return; | |||||
while (nl != NULL) { | |||||
if (nl->nb->info.type == NB_PIECE | if (nl->nb->info.type == NB_PIECE | ||||
&& nl->nb->info.index == index | && nl->nb->info.index == index | ||||
&& nl->nb->info.begin == begin | && nl->nb->info.begin == begin | ||||
&& nl->nb->info.length == length | && nl->nb->info.length == length) { | ||||
&& (nl != BTPDQ_FIRST(&p->outq) && p->outq_off > 0)) { | |||||
btpd_log(BTPD_L_MSG, "cancel matched.\n"); | |||||
struct nb_link *data = BTPDQ_NEXT(nl, entry); | struct nb_link *data = BTPDQ_NEXT(nl, entry); | ||||
nb_drop(nl->nb); | if (net_unsend(p, nl)) | ||||
BTPDQ_REMOVE(&p->outq, nl, entry); | net_unsend(p, data); | ||||
free(nl); | break; | ||||
nb_drop(data->nb); | |||||
BTPDQ_REMOVE(&p->outq, data, entry); | |||||
free(data); | |||||
} | } | ||||
nl = BTPDQ_NEXT(nl, entry); | |||||
} | |||||
if (BTPDQ_EMPTY(&p->outq)) { | |||||
if (p->flags & PF_ON_WRITEQ) { | |||||
BTPDQ_REMOVE(&btpd.writeq, p, wq_entry); | |||||
p->flags &= ~PF_ON_WRITEQ; | |||||
} else | |||||
event_del(&p->out_ev); | |||||
} | |||||
} | } | ||||
int | int | ||||