1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-06-30 19:12:48 -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

View File

@ -393,7 +393,7 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, int has_help,
* $XAUTHORITY is not reliable on Windows, so we provide a
* means to override it.
*/
if (!midsession && backend_from_proto(PROT_SSH)) {
if (!midsession && backend_vt_from_proto(PROT_SSH)) {
s = ctrl_getset(b, "Connection/SSH/X11", "x11", "X11 forwarding");
ctrl_filesel(s, "X authority file for local display", 't',
NULL, FALSE, "Select X authority file",

View File

@ -126,8 +126,7 @@ static int caret_x = -1, caret_y = -1;
static int kbd_codepage;
static Ldisc *ldisc;
static Backend *back;
static void *backhandle;
static Backend *backend;
static struct unicode_data ucsdata;
static int session_closed;
@ -248,6 +247,7 @@ char *get_ttymode(void *frontend, const char *mode)
static void start_backend(void)
{
const struct Backend_vtable *vt;
const char *error;
char msg[1024], *title;
char *realhost;
@ -257,8 +257,8 @@ static void start_backend(void)
* Select protocol. This is farmed out into a table in a
* separate file to enable an ssh-free variant.
*/
back = backend_from_proto(conf_get_int(conf, CONF_protocol));
if (back == NULL) {
vt = backend_vt_from_proto(conf_get_int(conf, CONF_protocol));
if (!vt) {
char *str = dupprintf("%s Internal Error", appname);
MessageBox(NULL, "Unsupported protocol number found",
str, MB_OK | MB_ICONEXCLAMATION);
@ -266,13 +266,13 @@ static void start_backend(void)
cleanup_exit(1);
}
error = back->init(NULL, &backhandle, conf,
conf_get_str(conf, CONF_host),
conf_get_int(conf, CONF_port),
&realhost,
conf_get_int(conf, CONF_tcp_nodelay),
conf_get_int(conf, CONF_tcp_keepalives));
back->provide_logctx(backhandle, logctx);
error = backend_init(vt, NULL, &backend, conf,
conf_get_str(conf, CONF_host),
conf_get_int(conf, CONF_port),
&realhost,
conf_get_int(conf, CONF_tcp_nodelay),
conf_get_int(conf, CONF_tcp_keepalives));
backend_provide_logctx(backend, logctx);
if (error) {
char *str = dupprintf("%s Error", appname);
sprintf(msg, "Unable to open connection to\n"
@ -294,12 +294,12 @@ static void start_backend(void)
/*
* Connect the terminal to the backend for resize purposes.
*/
term_provide_resize_fn(term, back->size, backhandle);
term_provide_backend(term, backend);
/*
* Set up a line discipline.
*/
ldisc = ldisc_create(conf, term, back, backhandle, NULL);
ldisc = ldisc_create(conf, term, backend, NULL);
/*
* Destroy the Restart Session menu item. (This will return
@ -329,11 +329,10 @@ static void close_session(void *ignored_context)
ldisc_free(ldisc);
ldisc = NULL;
}
if (back) {
back->free(backhandle);
backhandle = NULL;
back = NULL;
term_provide_resize_fn(term, NULL, NULL);
if (backend) {
backend_free(backend);
backend = NULL;
term_provide_backend(term, NULL);
update_specials_menu(NULL);
}
@ -413,10 +412,11 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
default_protocol = be_default_protocol;
/* Find the appropriate default port. */
{
Backend *b = backend_from_proto(default_protocol);
const struct Backend_vtable *vt =
backend_vt_from_proto(default_protocol);
default_port = 0; /* illegal */
if (b)
default_port = b->default_port;
if (vt)
default_port = vt->default_port;
}
conf_set_int(conf, CONF_logtype, LGTYP_NONE);
@ -951,8 +951,8 @@ void update_specials_menu(void *frontend)
HMENU new_menu;
int i, j;
if (back)
specials = back->get_specials(backhandle);
if (backend)
specials = backend_get_specials(backend);
else
specials = NULL;
@ -1975,7 +1975,7 @@ void notify_remote_exit(void *fe)
int exitcode, close_on_exit;
if (!session_closed &&
(exitcode = back->exitcode(backhandle)) >= 0) {
(exitcode = backend_exitcode(backend)) >= 0) {
close_on_exit = conf_get_int(conf, CONF_close_on_exit);
/* Abnormal exits will already have set session_closed and taken
* appropriate action. */
@ -2161,7 +2161,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
}
break;
case IDM_RESTART:
if (!back) {
if (!backend) {
logevent(NULL, "----- Session restarted -----");
term_pwron(term, FALSE);
start_backend();
@ -2190,7 +2190,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
prev_conf = conf_copy(conf);
reconfig_result =
do_reconfig(hwnd, back ? back->cfg_info(backhandle) : 0);
do_reconfig(hwnd, backend ? backend_cfg_info(backend) : 0);
reconfiguring = FALSE;
if (!reconfig_result) {
conf_free(prev_conf);
@ -2237,8 +2237,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
setup_clipboards(term, conf);
/* Pass new config data to the back end */
if (back)
back->reconfig(backhandle, conf);
if (backend)
backend_reconfig(backend, conf);
/* Screen size changed ? */
if (conf_get_int(conf, CONF_height) !=
@ -2414,8 +2414,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
*/
if (i >= n_specials)
break;
if (back)
back->special(backhandle, specials[i].code);
if (backend)
backend_special(backend, specials[i].code);
}
}
break;
@ -4405,8 +4405,8 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
return p - output;
}
if (wParam == VK_CANCEL && shift_state == 2) { /* Ctrl-Break */
if (back)
back->special(backhandle, TS_BRK);
if (backend)
backend_special(backend, TS_BRK);
return 0;
}
if (wParam == VK_PAUSE) { /* Break/Pause */

View File

@ -76,8 +76,7 @@ DWORD orig_console_mode;
WSAEVENT netevent;
static Backend *back;
static void *backhandle;
static Backend *backend;
static Conf *conf;
int term_ldisc(Terminal *term, int mode)
@ -254,11 +253,11 @@ int stdin_gotdata(struct handle *h, void *data, int len)
cleanup_exit(0);
}
noise_ultralight(len);
if (back->connected(backhandle)) {
if (backend_connected(backend)) {
if (len > 0) {
return back->send(backhandle, data, len);
return backend_send(backend, data, len);
} else {
back->special(backhandle, TS_EOF);
backend_special(backend, TS_EOF);
return 0;
}
} else
@ -281,9 +280,9 @@ void stdouterr_sent(struct handle *h, int new_backlog)
(h == stdout_handle ? "output" : "error"), buf);
cleanup_exit(0);
}
if (back->connected(backhandle)) {
back->unthrottle(backhandle, (handle_backlog(stdout_handle) +
handle_backlog(stderr_handle)));
if (backend_connected(backend)) {
backend_unthrottle(backend, (handle_backlog(stdout_handle) +
handle_backlog(stderr_handle)));
}
}
@ -300,6 +299,7 @@ int main(int argc, char **argv)
int use_subsystem = 0;
int just_test_share_exists = FALSE;
unsigned long now, next, then;
const struct Backend_vtable *vt;
dll_hijacking_protection();
@ -334,10 +334,10 @@ int main(int argc, char **argv)
*/
char *p = getenv("PLINK_PROTOCOL");
if (p) {
const Backend *b = backend_from_name(p);
if (b) {
default_protocol = b->protocol;
default_port = b->default_port;
const struct Backend_vtable *vt = backend_vt_from_name(p);
if (vt) {
default_protocol = vt->protocol;
default_port = vt->default_port;
conf_set_int(conf, CONF_protocol, default_protocol);
conf_set_int(conf, CONF_port, default_port);
}
@ -432,8 +432,8 @@ int main(int argc, char **argv)
* Select protocol. This is farmed out into a table in a
* separate file to enable an ssh-free variant.
*/
back = backend_from_proto(conf_get_int(conf, CONF_protocol));
if (back == NULL) {
vt = backend_vt_from_proto(conf_get_int(conf, CONF_protocol));
if (vt == NULL) {
fprintf(stderr,
"Internal fault: Unsupported protocol found\n");
return 1;
@ -460,13 +460,13 @@ int main(int argc, char **argv)
console_provide_logctx(logctx);
if (just_test_share_exists) {
if (!back->test_for_upstream) {
if (!vt->test_for_upstream) {
fprintf(stderr, "Connection sharing not supported for connection "
"type '%s'\n", back->name);
"type '%s'\n", vt->name);
return 1;
}
if (back->test_for_upstream(conf_get_str(conf, CONF_host),
conf_get_int(conf, CONF_port), conf))
if (vt->test_for_upstream(conf_get_str(conf, CONF_host),
conf_get_int(conf, CONF_port), conf))
return 0;
else
return 1;
@ -487,16 +487,16 @@ int main(int argc, char **argv)
int nodelay = conf_get_int(conf, CONF_tcp_nodelay) &&
(GetFileType(GetStdHandle(STD_INPUT_HANDLE)) == FILE_TYPE_CHAR);
error = back->init(NULL, &backhandle, conf,
conf_get_str(conf, CONF_host),
conf_get_int(conf, CONF_port),
&realhost, nodelay,
conf_get_int(conf, CONF_tcp_keepalives));
error = backend_init(vt, NULL, &backend, conf,
conf_get_str(conf, CONF_host),
conf_get_int(conf, CONF_port),
&realhost, nodelay,
conf_get_int(conf, CONF_tcp_keepalives));
if (error) {
fprintf(stderr, "Unable to open connection:\n%s", error);
return 1;
}
back->provide_logctx(backhandle, logctx);
backend_provide_logctx(backend, logctx);
sfree(realhost);
}
@ -532,7 +532,7 @@ int main(int argc, char **argv)
int n;
DWORD ticks;
if (!sending && back->sendok(backhandle)) {
if (!sending && backend_sendok(backend)) {
stdin_handle = handle_input_new(inhandle, stdin_gotdata, NULL,
0);
sending = TRUE;
@ -643,13 +643,13 @@ int main(int argc, char **argv)
sfree(handles);
if (sending)
handle_unthrottle(stdin_handle, back->sendbuffer(backhandle));
handle_unthrottle(stdin_handle, backend_sendbuffer(backend));
if (!back->connected(backhandle) &&
if (!backend_connected(backend) &&
handle_backlog(stdout_handle) + handle_backlog(stderr_handle) == 0)
break; /* we closed the connection */
}
exitcode = back->exitcode(backhandle);
exitcode = backend_exitcode(backend);
if (exitcode < 0) {
fprintf(stderr, "Remote process exit code unavailable\n");
exitcode = 1; /* this is an error condition */

View File

@ -17,6 +17,7 @@ typedef struct serial_backend_data {
int bufsize;
long clearbreak_time;
int break_in_progress;
Backend backend;
} *Serial;
static void serial_terminate(Serial serial)
@ -198,7 +199,7 @@ static const char *serial_configure(Serial serial, HANDLE serport, Conf *conf)
* Also places the canonical host name into `realhost'. It must be
* freed by the caller.
*/
static const char *serial_init(void *frontend_handle, void **backend_handle,
static const char *serial_init(void *frontend_handle, Backend **backend_handle,
Conf *conf, const char *host, int port,
char **realhost, int nodelay, int keepalive)
{
@ -212,7 +213,8 @@ static const char *serial_init(void *frontend_handle, void **backend_handle,
serial->out = serial->in = NULL;
serial->bufsize = 0;
serial->break_in_progress = FALSE;
*backend_handle = serial;
serial->backend.vt = &serial_backend;
*backend_handle = &serial->backend;
serial->frontend = frontend_handle;
@ -279,18 +281,18 @@ static const char *serial_init(void *frontend_handle, void **backend_handle,
return NULL;
}
static void serial_free(void *handle)
static void serial_free(Backend *be)
{
Serial serial = (Serial) handle;
Serial serial = FROMFIELD(be, struct serial_backend_data, backend);
serial_terminate(serial);
expire_timer_context(serial);
sfree(serial);
}
static void serial_reconfig(void *handle, Conf *conf)
static void serial_reconfig(Backend *be, Conf *conf)
{
Serial serial = (Serial) handle;
Serial serial = FROMFIELD(be, struct serial_backend_data, backend);
serial_configure(serial, serial->port, conf);
@ -303,9 +305,9 @@ static void serial_reconfig(void *handle, Conf *conf)
/*
* Called to send data down the serial connection.
*/
static int serial_send(void *handle, const char *buf, int len)
static int serial_send(Backend *be, const char *buf, int len)
{
Serial serial = (Serial) handle;
Serial serial = FROMFIELD(be, struct serial_backend_data, backend);
if (serial->out == NULL)
return 0;
@ -317,16 +319,16 @@ static int serial_send(void *handle, const char *buf, int len)
/*
* Called to query the current sendability status.
*/
static int serial_sendbuffer(void *handle)
static int serial_sendbuffer(Backend *be)
{
Serial serial = (Serial) handle;
Serial serial = FROMFIELD(be, struct serial_backend_data, backend);
return serial->bufsize;
}
/*
* Called to set the size of the window
*/
static void serial_size(void *handle, int width, int height)
static void serial_size(Backend *be, int width, int height)
{
/* Do nothing! */
return;
@ -346,9 +348,9 @@ static void serbreak_timer(void *ctx, unsigned long now)
/*
* Send serial special codes.
*/
static void serial_special(void *handle, Telnet_Special code)
static void serial_special(Backend *be, Telnet_Special code)
{
Serial serial = (Serial) handle;
Serial serial = FROMFIELD(be, struct serial_backend_data, backend);
if (serial->port && code == TS_BRK) {
logevent(serial->frontend, "Starting serial break at user request");
@ -375,7 +377,7 @@ static void serial_special(void *handle, Telnet_Special code)
* Return a list of the special codes that make sense in this
* protocol.
*/
static const struct telnet_special *serial_get_specials(void *handle)
static const struct telnet_special *serial_get_specials(Backend *be)
{
static const struct telnet_special specials[] = {
{"Break", TS_BRK},
@ -384,24 +386,24 @@ static const struct telnet_special *serial_get_specials(void *handle)
return specials;
}
static int serial_connected(void *handle)
static int serial_connected(Backend *be)
{
return 1; /* always connected */
}
static int serial_sendok(void *handle)
static int serial_sendok(Backend *be)
{
return 1;
}
static void serial_unthrottle(void *handle, int backlog)
static void serial_unthrottle(Backend *be, int backlog)
{
Serial serial = (Serial) handle;
Serial serial = FROMFIELD(be, struct serial_backend_data, backend);
if (serial->in)
handle_unthrottle(serial->in, backlog);
}
static int serial_ldisc(void *handle, int option)
static int serial_ldisc(Backend *be, int option)
{
/*
* Local editing and local echo are off by default.
@ -409,19 +411,19 @@ static int serial_ldisc(void *handle, int option)
return 0;
}
static void serial_provide_ldisc(void *handle, Ldisc *ldisc)
static void serial_provide_ldisc(Backend *be, Ldisc *ldisc)
{
/* This is a stub. */
}
static void serial_provide_logctx(void *handle, LogContext *logctx)
static void serial_provide_logctx(Backend *be, LogContext *logctx)
{
/* This is a stub. */
}
static int serial_exitcode(void *handle)
static int serial_exitcode(Backend *be)
{
Serial serial = (Serial) handle;
Serial serial = FROMFIELD(be, struct serial_backend_data, backend);
if (serial->port != INVALID_HANDLE_VALUE)
return -1; /* still connected */
else
@ -432,12 +434,12 @@ static int serial_exitcode(void *handle)
/*
* cfg_info for Serial does nothing at all.
*/
static int serial_cfg_info(void *handle)
static int serial_cfg_info(Backend *be)
{
return 0;
}
Backend serial_backend = {
const struct Backend_vtable serial_backend = {
serial_init,
serial_free,
serial_reconfig,

View File

@ -596,7 +596,7 @@ void agent_schedule_callback(void (*callback)(void *, void *, int),
/*
* Exports from winser.c.
*/
extern Backend serial_backend;
extern const struct Backend_vtable serial_backend;
/*
* Exports from winjump.c.