1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-07-05 21:42:47 -05:00

Turn Backend into a sensible classoid.

Nearly every part of the code that ever handles a full backend
structure has historically done it using a pair of pointer variables,
one pointing at a constant struct full of function pointers, and the
other pointing to a 'void *' state object that's passed to each of
those.

While I'm modernising the rest of the code, this seems like a good
time to turn that into the same more or less type-safe and less
cumbersome system as I'm using for other parts of the code, such as
Socket, Plug, BinaryPacketProtocol and so forth: the Backend structure
contains a vtable pointer, and a system of macro wrappers handles
dispatching through that vtable.
This commit is contained in:
Simon Tatham
2018-09-11 16:23:38 +01:00
parent c51fe7c217
commit eefebaaa9e
36 changed files with 633 additions and 611 deletions

92
ssh.c
View File

@ -561,14 +561,14 @@ struct ssh_portfwd {
static void ssh1_protocol_setup(Ssh ssh);
static void ssh2_protocol_setup(Ssh ssh);
static void ssh2_bare_connection_protocol_setup(Ssh ssh);
static void ssh_size(void *handle, int width, int height);
static void ssh_special(void *handle, Telnet_Special);
static void ssh_size(Backend *be, int width, int height);
static void ssh_special(Backend *be, Telnet_Special);
static int ssh2_try_send(struct ssh_channel *c);
static int ssh_send_channel_data(struct ssh_channel *c,
const char *buf, int len);
static void ssh_throttle_all(Ssh ssh, int enable, int bufsize);
static void ssh2_set_window(struct ssh_channel *c, int newwin);
static int ssh_sendbuffer(void *handle);
static int ssh_sendbuffer(Backend *be);
static int ssh_do_close(Ssh ssh, int notify_exit);
static void ssh2_timer(void *ctx, unsigned long now);
static int ssh2_timer_update(Ssh ssh, unsigned long rekey_time);
@ -699,6 +699,7 @@ struct ssh_tag {
Socket s;
const Plug_vtable *plugvt;
Backend backend;
Ldisc *ldisc;
LogContext *logctx;
@ -1877,7 +1878,7 @@ static void do_ssh_init(Ssh ssh)
update_specials_menu(ssh->frontend);
ssh->state = SSH_STATE_BEFORE_SIZE;
ssh->pinger = pinger_new(ssh->conf, &ssh_backend, ssh);
ssh->pinger = pinger_new(ssh->conf, &ssh->backend);
sfree(s->vstring);
@ -2029,7 +2030,7 @@ static void do_ssh_connection_init(Ssh ssh)
update_specials_menu(ssh->frontend);
ssh->state = SSH_STATE_BEFORE_SIZE;
ssh->pinger = pinger_new(ssh->conf, &ssh_backend, ssh);
ssh->pinger = pinger_new(ssh->conf, &ssh->backend);
/*
* Get connection protocol under way.
@ -4726,9 +4727,9 @@ static void do_ssh1_connection(void *vctx)
ssh->state = SSH_STATE_SESSION;
if (ssh->size_needed)
ssh_size(ssh, ssh->term_width, ssh->term_height);
backend_size(&ssh->backend, ssh->term_width, ssh->term_height);
if (ssh->eof_needed)
ssh_special(ssh, TS_EOF);
backend_special(&ssh->backend, TS_EOF);
if (ssh->ldisc)
ldisc_echoedit_update(ssh->ldisc); /* cause ldisc to notice changes */
@ -10110,9 +10111,9 @@ static void do_ssh2_connection(void *vctx)
ssh->state = SSH_STATE_SESSION;
if (ssh->size_needed)
ssh_size(ssh, ssh->term_width, ssh->term_height);
backend_size(&ssh->backend, ssh->term_width, ssh->term_height);
if (ssh->eof_needed)
ssh_special(ssh, TS_EOF);
backend_special(&ssh->backend, TS_EOF);
/*
* Transfer data!
@ -10664,7 +10665,7 @@ static void ssh_cache_conf_values(Ssh ssh)
*
* Returns an error message, or NULL on success.
*/
static const char *ssh_init(void *frontend_handle, void **backend_handle,
static const char *ssh_init(void *frontend_handle, Backend **backend_handle,
Conf *conf,
const char *host, int port, char **realhost,
int nodelay, int keepalive)
@ -10777,7 +10778,8 @@ static const char *ssh_init(void *frontend_handle, void **backend_handle,
#endif
ssh->gss_kex_used = FALSE;
*backend_handle = ssh;
ssh->backend.vt = &ssh_backend;
*backend_handle = &ssh->backend;
ssh->frontend = frontend_handle;
ssh->term_width = conf_get_int(ssh->conf, CONF_width);
@ -10826,9 +10828,9 @@ static const char *ssh_init(void *frontend_handle, void **backend_handle,
return NULL;
}
static void ssh_free(void *handle)
static void ssh_free(Backend *be)
{
Ssh ssh = (Ssh) handle;
Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
struct ssh_channel *c;
struct ssh_rportfwd *pf;
struct X11FakeAuth *auth;
@ -10937,9 +10939,9 @@ static void ssh_free(void *handle)
/*
* Reconfigure the SSH backend.
*/
static void ssh_reconfig(void *handle, Conf *conf)
static void ssh_reconfig(Backend *be, Conf *conf)
{
Ssh ssh = (Ssh) handle;
Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
const char *rekeying = NULL;
int rekey_mandatory = FALSE;
unsigned long old_max_data_size;
@ -10999,9 +11001,9 @@ static void ssh_reconfig(void *handle, Conf *conf)
/*
* Called to send data down the SSH connection.
*/
static int ssh_send(void *handle, const char *buf, int len)
static int ssh_send(Backend *be, const char *buf, int len)
{
Ssh ssh = (Ssh) handle;
Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
if (ssh == NULL || ssh->s == NULL)
return 0;
@ -11009,15 +11011,15 @@ static int ssh_send(void *handle, const char *buf, int len)
bufchain_add(&ssh->user_input, buf, len);
queue_idempotent_callback(&ssh->user_input_consumer);
return ssh_sendbuffer(ssh);
return backend_sendbuffer(&ssh->backend);
}
/*
* Called to query the current amount of buffered stdin data.
*/
static int ssh_sendbuffer(void *handle)
static int ssh_sendbuffer(Backend *be)
{
Ssh ssh = (Ssh) handle;
Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
int override_value;
if (ssh == NULL || ssh->s == NULL)
@ -11047,9 +11049,9 @@ static int ssh_sendbuffer(void *handle)
/*
* Called to set the size of the window from SSH's POV.
*/
static void ssh_size(void *handle, int width, int height)
static void ssh_size(Backend *be, int width, int height)
{
Ssh ssh = (Ssh) handle;
Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
PktOut *pktout;
ssh->term_width = width;
@ -11090,7 +11092,7 @@ static void ssh_size(void *handle, int width, int height)
* Return a list of the special codes that make sense in this
* protocol.
*/
static const struct telnet_special *ssh_get_specials(void *handle)
static const struct telnet_special *ssh_get_specials(Backend *be)
{
static const struct telnet_special ssh1_ignore_special[] = {
{"IGNORE message", TS_NOP}
@ -11126,7 +11128,7 @@ static const struct telnet_special *ssh_get_specials(void *handle)
struct telnet_special *specials = NULL;
int nspecials = 0, specialsize = 0;
Ssh ssh = (Ssh) handle;
Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
sfree(ssh->specials);
@ -11196,9 +11198,9 @@ static const struct telnet_special *ssh_get_specials(void *handle)
* can send an EOF and collect resulting output (e.g. `plink
* hostname sort').
*/
static void ssh_special(void *handle, Telnet_Special code)
static void ssh_special(Backend *be, Telnet_Special code)
{
Ssh ssh = (Ssh) handle;
Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
PktOut *pktout;
if (code == TS_EOF) {
@ -11344,9 +11346,9 @@ void ssh_send_packet_from_downstream(Ssh ssh, unsigned id, int type,
* This is called when stdout/stderr (the entity to which
* from_backend sends data) manages to clear some backlog.
*/
static void ssh_unthrottle(void *handle, int bufsize)
static void ssh_unthrottle(Backend *be, int bufsize)
{
Ssh ssh = (Ssh) handle;
Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
if (ssh->version == 1) {
if (ssh->v1_stdout_throttling && bufsize < SSH1_BUFFER_LIMIT) {
@ -11405,21 +11407,21 @@ void ssh_send_port_open(void *channel, const char *hostname, int port,
}
}
static int ssh_connected(void *handle)
static int ssh_connected(Backend *be)
{
Ssh ssh = (Ssh) handle;
Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
return ssh->s != NULL;
}
static int ssh_sendok(void *handle)
static int ssh_sendok(Backend *be)
{
Ssh ssh = (Ssh) handle;
Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
return ssh->send_ok;
}
static int ssh_ldisc(void *handle, int option)
static int ssh_ldisc(Backend *be, int option)
{
Ssh ssh = (Ssh) handle;
Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
if (option == LD_ECHO)
return ssh->echoing;
if (option == LD_EDIT)
@ -11427,21 +11429,21 @@ static int ssh_ldisc(void *handle, int option)
return FALSE;
}
static void ssh_provide_ldisc(void *handle, Ldisc *ldisc)
static void ssh_provide_ldisc(Backend *be, Ldisc *ldisc)
{
Ssh ssh = (Ssh) handle;
Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
ssh->ldisc = ldisc;
}
static void ssh_provide_logctx(void *handle, LogContext *logctx)
static void ssh_provide_logctx(Backend *be, LogContext *logctx)
{
Ssh ssh = (Ssh) handle;
Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
ssh->logctx = logctx;
}
static int ssh_return_exitcode(void *handle)
static int ssh_return_exitcode(Backend *be)
{
Ssh ssh = (Ssh) handle;
Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
if (ssh->s != NULL)
return -1;
else
@ -11453,9 +11455,9 @@ static int ssh_return_exitcode(void *handle)
* (1 or 2 for the full SSH-1 or SSH-2 protocol; -1 for the bare
* SSH-2 connection protocol, i.e. a downstream; 0 for not-decided-yet.)
*/
static int ssh_cfg_info(void *handle)
static int ssh_cfg_info(Backend *be)
{
Ssh ssh = (Ssh) handle;
Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
if (ssh->version == 0)
return 0; /* don't know yet */
else if (ssh->bare_connection)
@ -11469,13 +11471,13 @@ static int ssh_cfg_info(void *handle)
* that fails. This variable is the means by which scp.c can reach
* into the SSH code and find out which one it got.
*/
extern int ssh_fallback_cmd(void *handle)
extern int ssh_fallback_cmd(Backend *be)
{
Ssh ssh = (Ssh) handle;
Ssh ssh = FROMFIELD(be, struct ssh_tag, backend);
return ssh->fallback_cmd;
}
Backend ssh_backend = {
const struct Backend_vtable ssh_backend = {
ssh_init,
ssh_free,
ssh_reconfig,