summaryrefslogtreecommitdiff
path: root/accel-pppd/cli/telnet.c
diff options
context:
space:
mode:
Diffstat (limited to 'accel-pppd/cli/telnet.c')
-rw-r--r--accel-pppd/cli/telnet.c51
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)