diff options
Diffstat (limited to 'accel-pppd/cli/telnet.c')
-rw-r--r-- | accel-pppd/cli/telnet.c | 51 |
1 files changed, 33 insertions, 18 deletions
diff --git a/accel-pppd/cli/telnet.c b/accel-pppd/cli/telnet.c index 6c41769e..9ef2ea84 100644 --- a/accel-pppd/cli/telnet.c +++ b/accel-pppd/cli/telnet.c @@ -477,10 +477,8 @@ static int cln_read(struct triton_md_handler_t *h) while (1) { n = read(h->fd, recv_buf, RECV_BUF_SIZE); - if (n == 0) { - disconnect(cln); - return -1; - } + if (n == 0) + goto disconn_soft; if (n < 0) { if (errno != EAGAIN) log_error("cli: telnet: read: %s\n", strerror(errno)); @@ -492,13 +490,25 @@ static int cln_read(struct triton_md_handler_t *h) if (telnet_input_char(cln, recv_buf[i])) break; } - if (cln->disconnect) { - disconnect(cln); - return -1; - } + + if (cln->disconnect) + goto disconn_soft; } return 0; + +disconn_soft: + /* Wait for pending data to be transmitted before disconnecting */ + if (cln->xmit_buf) { + triton_md_disable_handler(&cln->hnd, MD_MODE_READ); + cln->disconnect = 1; + + return 0; + } + + disconnect(cln); + + return -1; } static int cln_write(struct triton_md_handler_t *h) @@ -506,10 +516,7 @@ static int cln_write(struct triton_md_handler_t *h) struct telnet_client_t *cln = container_of(h, typeof(*cln), hnd); int k; - if (!cln->xmit_buf) - return 0; - - while (1) { + while (cln->xmit_buf) { for (; cln->xmit_pos < cln->xmit_buf->size; cln->xmit_pos += k) { k = write(cln->hnd.fd, cln->xmit_buf->buf + cln->xmit_pos, cln->xmit_buf->size - cln->xmit_pos); if (k < 0) { @@ -517,8 +524,7 @@ static int cln_write(struct triton_md_handler_t *h) return 0; if (errno != EPIPE) log_error("cli: telnet: write: %s\n", strerror(errno)); - disconnect(cln); - return -1; + goto disconn; } } @@ -527,16 +533,25 @@ static int cln_write(struct triton_md_handler_t *h) if (list_empty(&cln->xmit_queue)) { cln->xmit_buf = NULL; - break; + } else { + cln->xmit_buf = list_first_entry(&cln->xmit_queue, + typeof(*cln->xmit_buf), + entry); + list_del(&cln->xmit_buf->entry); } - - cln->xmit_buf = list_entry(cln->xmit_queue.next, typeof(*cln->xmit_buf), entry); - list_del(&cln->xmit_buf->entry); } + if (cln->disconnect) + goto disconn; + triton_md_disable_handler(&cln->hnd, MD_MODE_WRITE); return 0; + +disconn: + disconnect(cln); + + return -1; } static int serv_read(struct triton_md_handler_t *h) |