From 9f0e7d291558989cc44f98cf8603d5cf2787ce3a Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Tue, 14 Sep 2021 10:13:28 +0100 Subject: [PATCH] Backends: notify ldisc when sendok becomes true. (NFC) I've introduced a function ldisc_notify_sendok(), which backends should call on their ldisc (if they have one) when anything changes that might cause backend_sendok() to start returning true. At the moment, the function does nothing. But in future, I'm going to make ldisc start buffering typed-ahead input data not yet sent to the backend, and then the effect of this function will be to trigger flushing all that data into the backend. Backends only have to call this function if sendok was previously false: backends requiring no network connection stage (like pty and serial) can safely return true from sendok, and in that case, they don't also have to immediately call this function. --- ldisc.c | 4 ++++ otherbackends/raw.c | 6 +++++- otherbackends/rlogin.c | 6 +++++- otherbackends/supdup.c | 5 +++++ otherbackends/telnet.c | 2 ++ pscp.c | 1 + psftp.c | 1 + putty.h | 1 + ssh.h | 1 + ssh/connection1.c | 2 ++ ssh/connection2.c | 2 ++ ssh/server.c | 2 ++ ssh/ssh.c | 8 ++++++++ 13 files changed, 39 insertions(+), 2 deletions(-) diff --git a/ldisc.c b/ldisc.c index e5e1449d..8c985f06 100644 --- a/ldisc.c +++ b/ldisc.c @@ -139,6 +139,10 @@ void ldisc_echoedit_update(Ldisc *ldisc) seat_echoedit_update(ldisc->seat, ECHOING, EDITING); } +void ldisc_check_sendok(Ldisc *ldisc) +{ +} + void ldisc_send(Ldisc *ldisc, const void *vbuf, int len, bool interactive) { const char *buf = (const char *)vbuf; diff --git a/otherbackends/raw.c b/otherbackends/raw.c index 87a136ba..97b7be09 100644 --- a/otherbackends/raw.c +++ b/otherbackends/raw.c @@ -17,6 +17,7 @@ struct Raw { size_t bufsize; Seat *seat; LogContext *logctx; + Ldisc *ldisc; bool sent_console_eof, sent_socket_eof, socket_connected; Conf *conf; @@ -41,6 +42,8 @@ static void raw_log(Plug *plug, PlugLogType type, SockAddr *addr, int port, error_code, raw->conf, raw->socket_connected); if (type == PLUGLOG_CONNECT_SUCCESS) { raw->socket_connected = true; + if (raw->ldisc) + ldisc_check_sendok(raw->ldisc); if (is_tempseat(raw->seat)) { Seat *ts = raw->seat; tempseat_flush(ts); @@ -295,7 +298,8 @@ static bool raw_ldisc(Backend *be, int option) static void raw_provide_ldisc(Backend *be, Ldisc *ldisc) { - /* This is a stub. */ + Raw *raw = container_of(be, Raw, backend); + raw->ldisc = ldisc; } static int raw_exitcode(Backend *be) diff --git a/otherbackends/rlogin.c b/otherbackends/rlogin.c index 51e6ed05..11deb89c 100644 --- a/otherbackends/rlogin.c +++ b/otherbackends/rlogin.c @@ -22,6 +22,7 @@ struct Rlogin { int term_width, term_height; Seat *seat; LogContext *logctx; + Ldisc *ldisc; Conf *conf; @@ -194,6 +195,8 @@ static void rlogin_startup(Rlogin *rlogin, int prompt_result, } rlogin->prompt = NULL; + if (rlogin->ldisc) + ldisc_check_sendok(rlogin->ldisc); } static const PlugVtable Rlogin_plugvt = { @@ -413,7 +416,8 @@ static bool rlogin_ldisc(Backend *be, int option) static void rlogin_provide_ldisc(Backend *be, Ldisc *ldisc) { - /* This is a stub. */ + Rlogin *rlogin = container_of(be, Rlogin, backend); + rlogin->ldisc = ldisc; } static int rlogin_exitcode(Backend *be) diff --git a/otherbackends/supdup.c b/otherbackends/supdup.c index ae7e67f7..a3418fe1 100644 --- a/otherbackends/supdup.c +++ b/otherbackends/supdup.c @@ -71,6 +71,7 @@ struct supdup_tag Seat *seat; LogContext *logctx; + Ldisc *ldisc; int term_width, term_height; long long ttyopt; @@ -565,6 +566,8 @@ static void supdup_log(Plug *plug, PlugLogType type, SockAddr *addr, int port, supdup->conf, supdup->socket_connected); if (type == PLUGLOG_CONNECT_SUCCESS) { supdup->socket_connected = true; + if (supdup->ldisc) + ldisc_check_sendok(supdup->ldisc); if (is_tempseat(supdup->seat)) { Seat *ts = supdup->seat; tempseat_flush(ts); @@ -893,6 +896,8 @@ static bool supdup_ldisc(Backend *be, int option) static void supdup_provide_ldisc(Backend *be, Ldisc *ldisc) { + Supdup *supdup = container_of(be, Supdup, backend); + supdup->ldisc = ldisc; } static int supdup_exitcode(Backend *be) diff --git a/otherbackends/telnet.c b/otherbackends/telnet.c index 540d384c..98c202c6 100644 --- a/otherbackends/telnet.c +++ b/otherbackends/telnet.c @@ -628,6 +628,8 @@ static void telnet_log(Plug *plug, PlugLogType type, SockAddr *addr, int port, telnet->socket_connected); if (type == PLUGLOG_CONNECT_SUCCESS) { telnet->socket_connected = true; + if (telnet->ldisc) + ldisc_check_sendok(telnet->ldisc); if (is_tempseat(telnet->seat)) { Seat *ts = telnet->seat; tempseat_flush(ts); diff --git a/pscp.c b/pscp.c index ec4dfa8a..7717d8d6 100644 --- a/pscp.c +++ b/pscp.c @@ -58,6 +58,7 @@ const char *const appname = "PSCP"; #define MAX_SCP_BUFSIZE 16384 void ldisc_echoedit_update(Ldisc *ldisc) { } +void ldisc_check_sendok(Ldisc *ldisc) { } static size_t pscp_output(Seat *, bool is_stderr, const void *, size_t); static bool pscp_eof(Seat *); diff --git a/psftp.c b/psftp.c index 16beee56..a09837c7 100644 --- a/psftp.c +++ b/psftp.c @@ -2448,6 +2448,7 @@ int do_sftp(int mode, int modeflags, char *batchfile) static bool verbose = false; void ldisc_echoedit_update(Ldisc *ldisc) { } +void ldisc_check_sendok(Ldisc *ldisc) { } /* * Receive a block of data from the SSH link. Block until all data diff --git a/putty.h b/putty.h index 8b419a32..fcfff4b6 100644 --- a/putty.h +++ b/putty.h @@ -2055,6 +2055,7 @@ void ldisc_configure(Ldisc *, Conf *); void ldisc_free(Ldisc *); void ldisc_send(Ldisc *, const void *buf, int len, bool interactive); void ldisc_echoedit_update(Ldisc *); +void ldisc_check_sendok(Ldisc *); /* * Exports from sshrand.c. diff --git a/ssh.h b/ssh.h index 23bed390..34a8909d 100644 --- a/ssh.h +++ b/ssh.h @@ -397,6 +397,7 @@ LogContext *ssh_get_logctx(Ssh *ssh); void ssh_throttle_conn(Ssh *ssh, int adjust); void ssh_got_exitcode(Ssh *ssh, int status); void ssh_ldisc_update(Ssh *ssh); +void ssh_check_sendok(Ssh *ssh); void ssh_got_fallback_cmd(Ssh *ssh); bool ssh_is_bare(Ssh *ssh); diff --git a/ssh/connection1.c b/ssh/connection1.c index 7b1765f6..071e0139 100644 --- a/ssh/connection1.c +++ b/ssh/connection1.c @@ -775,6 +775,8 @@ static void ssh1_set_wants_user_input(ConnectionLayer *cl, bool wanted) s->want_user_input = wanted; s->finished_setup = true; + if (wanted) + ssh_check_sendok(s->ppl.ssh); } static bool ssh1_connection_want_user_input(PacketProtocolLayer *ppl) diff --git a/ssh/connection2.c b/ssh/connection2.c index 2e7102db..86e26f4b 100644 --- a/ssh/connection2.c +++ b/ssh/connection2.c @@ -1709,6 +1709,8 @@ static void ssh2_set_wants_user_input(ConnectionLayer *cl, bool wanted) container_of(cl, struct ssh2_connection_state, cl); s->want_user_input = wanted; + if (wanted) + ssh_check_sendok(s->ppl.ssh); } static bool ssh2_connection_want_user_input(PacketProtocolLayer *ppl) diff --git a/ssh/server.c b/ssh/server.c index 1517522b..a3c400c0 100644 --- a/ssh/server.c +++ b/ssh/server.c @@ -244,6 +244,8 @@ Conf *make_ssh_server_conf(void) return conf; } +void ssh_check_sendok(Ssh *ssh) {} + static const PlugVtable ssh_server_plugvt = { .log = server_socket_log, .closing = server_closing, diff --git a/ssh/ssh.c b/ssh/ssh.c index 98b7a68a..10c52001 100644 --- a/ssh/ssh.c +++ b/ssh/ssh.c @@ -1156,6 +1156,14 @@ static bool ssh_sendok(Backend *be) return ssh->base_layer && ssh_ppl_want_user_input(ssh->base_layer); } +void ssh_check_sendok(Ssh *ssh) +{ + /* Called when the connection layer might have caused ssh_sendok + * to start returning true */ + if (ssh->ldisc) + ldisc_check_sendok(ssh->ldisc); +} + void ssh_ldisc_update(Ssh *ssh) { /* Called when the connection layer wants to propagate an update