1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 09:27:59 +00: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

@ -22,7 +22,7 @@ const int be_default_protocol = PROT_TELNET;
const int be_default_protocol = PROT_SSH;
#endif
Backend *backends[] = {
const struct Backend_vtable *const backends[] = {
&ssh_backend,
&telnet_backend,
&rlogin_backend,

View File

@ -22,7 +22,7 @@ const int be_default_protocol = PROT_TELNET;
const int be_default_protocol = PROT_SSH;
#endif
Backend *backends[] = {
const struct Backend_vtable *const backends[] = {
&ssh_backend,
&telnet_backend,
&rlogin_backend,

View File

@ -6,6 +6,6 @@
#include <stdio.h>
#include "putty.h"
Backend *backends[] = {
const struct Backend_vtable *const backends[] = {
NULL
};

View File

@ -10,7 +10,7 @@ const int be_default_protocol = PROT_TELNET;
const char *const appname = "PuTTYtel";
Backend *backends[] = {
const struct Backend_vtable *const backends[] = {
&telnet_backend,
&rlogin_backend,
&raw_backend,

View File

@ -10,7 +10,7 @@ const int be_default_protocol = PROT_TELNET;
const char *const appname = "PuTTYtel";
Backend *backends[] = {
const struct Backend_vtable *const backends[] = {
&telnet_backend,
&rlogin_backend,
&raw_backend,

View File

@ -10,7 +10,7 @@
const int be_default_protocol = PROT_SSH;
Backend *backends[] = {
const struct Backend_vtable *const backends[] = {
&ssh_backend,
NULL
};

View File

@ -275,13 +275,14 @@ int cmdline_process_param(const char *p, char *value,
const char *comma = strchr(p, ',');
if (comma) {
char *prefix = dupprintf("%.*s", (int)(comma - p), p);
const Backend *b = backend_from_name(prefix);
const struct Backend_vtable *vt =
backend_vt_from_name(prefix);
if (b) {
default_protocol = b->protocol;
if (vt) {
default_protocol = vt->protocol;
conf_set_int(conf, CONF_protocol,
default_protocol);
port_override = b->default_port;
port_override = vt->default_port;
} else {
cmdline_error("unrecognised protocol prefix '%s'",
prefix);

View File

@ -267,10 +267,10 @@ void config_protocolbuttons_handler(union control *ctrl, void *dlg,
conf_set_int(conf, CONF_protocol, newproto);
if (oldproto != newproto) {
Backend *ob = backend_from_proto(oldproto);
Backend *nb = backend_from_proto(newproto);
assert(ob);
assert(nb);
const struct Backend_vtable *ovt = backend_vt_from_proto(oldproto);
const struct Backend_vtable *nvt = backend_vt_from_proto(newproto);
assert(ovt);
assert(nvt);
/* Iff the user hasn't changed the port from the old protocol's
* default, update it with the new protocol's default.
* (This includes a "default" of 0, implying that there is no
@ -281,8 +281,8 @@ void config_protocolbuttons_handler(union control *ctrl, void *dlg,
* getting to the protocol; we want that non-default port
* to be preserved. */
port = conf_get_int(conf, CONF_port);
if (port == ob->default_port)
conf_set_int(conf, CONF_port, nb->default_port);
if (port == ovt->default_port)
conf_set_int(conf, CONF_port, nvt->default_port);
}
dlg_refresh(hp->host, dlg);
dlg_refresh(hp->port, dlg);
@ -1503,7 +1503,7 @@ void setup_config_box(struct controlbox *b, int midsession,
hp->port = c;
ctrl_columns(s, 1, 100);
if (!backend_from_proto(PROT_SSH)) {
if (!backend_vt_from_proto(PROT_SSH)) {
ctrl_radiobuttons(s, "Connection type:", NO_SHORTCUT, 3,
HELPCTX(session_hostname),
config_protocolbuttons_handler, P(hp),
@ -1594,7 +1594,7 @@ void setup_config_box(struct controlbox *b, int midsession,
{
const char *sshlogname, *sshrawlogname;
if ((midsession && protocol == PROT_SSH) ||
(!midsession && backend_from_proto(PROT_SSH))) {
(!midsession && backend_vt_from_proto(PROT_SSH))) {
sshlogname = "SSH packets";
sshrawlogname = "SSH packets and raw data";
} else {
@ -1630,7 +1630,7 @@ void setup_config_box(struct controlbox *b, int midsession,
conf_checkbox_handler, I(CONF_logflush));
if ((midsession && protocol == PROT_SSH) ||
(!midsession && backend_from_proto(PROT_SSH))) {
(!midsession && backend_vt_from_proto(PROT_SSH))) {
s = ctrl_getset(b, "Session/Logging", "ssh",
"Options specific to SSH packet logging");
ctrl_checkbox(s, "Omit known password fields", 'k',
@ -2107,7 +2107,7 @@ void setup_config_box(struct controlbox *b, int midsession,
#endif
{
const char *label = backend_from_proto(PROT_SSH) ?
const char *label = backend_vt_from_proto(PROT_SSH) ?
"Logical name of remote host (e.g. for SSH key lookup):" :
"Logical name of remote host:";
s = ctrl_getset(b, "Connection", "identity",
@ -2319,7 +2319,8 @@ void setup_config_box(struct controlbox *b, int midsession,
* when we're not doing SSH.
*/
if (backend_from_proto(PROT_SSH) && (!midsession || protocol == PROT_SSH)) {
if (backend_vt_from_proto(PROT_SSH) &&
(!midsession || protocol == PROT_SSH)) {
/*
* The Connection/SSH panel.

5
defs.h
View File

@ -21,7 +21,6 @@
#endif
typedef struct conf_tag Conf;
typedef struct backend_tag Backend;
typedef struct terminal_tag Terminal;
typedef struct Filename Filename;
@ -44,10 +43,14 @@ typedef struct SockAddr_tag *SockAddr;
typedef struct Socket_vtable Socket_vtable;
typedef struct Plug_vtable Plug_vtable;
typedef struct Backend Backend;
typedef struct Backend_vtable Backend_vtable;
typedef struct Ldisc_tag Ldisc;
typedef struct LogContext_tag LogContext;
typedef struct ssh_tag *Ssh;
/* Note indirection: for historical reasons (it used to be closer to
* the OS socket type), the type that most code uses for a socket is
* 'Socket', not 'Socket *'. So an implementation of Socket or Plug

55
ldisc.c
View File

@ -15,11 +15,11 @@
#define ECHOING (ldisc->localecho == FORCE_ON || \
(ldisc->localecho == AUTO && \
(ldisc->back->ldisc(ldisc->backhandle, LD_ECHO) || \
(backend_ldisc_option_state(ldisc->backend, LD_ECHO) || \
term_ldisc(ldisc->term, LD_ECHO))))
#define EDITING (ldisc->localedit == FORCE_ON || \
(ldisc->localedit == AUTO && \
(ldisc->back->ldisc(ldisc->backhandle, LD_EDIT) || \
(backend_ldisc_option_state(ldisc->backend, LD_EDIT) || \
term_ldisc(ldisc->term, LD_EDIT))))
static void c_write(Ldisc *ldisc, const void *buf, int len)
@ -78,8 +78,7 @@ static void bsb(Ldisc *ldisc, int n)
#define KCTRL(x) ((x^'@') | 0x100)
Ldisc *ldisc_create(Conf *conf, Terminal *term,
Backend *back, void *backhandle,
void *frontend)
Backend *backend, void *frontend)
{
Ldisc *ldisc = snew(Ldisc);
@ -88,8 +87,7 @@ Ldisc *ldisc_create(Conf *conf, Terminal *term,
ldisc->bufsiz = 0;
ldisc->quotenext = 0;
ldisc->back = back;
ldisc->backhandle = backhandle;
ldisc->backend = backend;
ldisc->term = term;
ldisc->frontend = frontend;
@ -98,8 +96,8 @@ Ldisc *ldisc_create(Conf *conf, Terminal *term,
/* Link ourselves into the backend and the terminal */
if (term)
term->ldisc = ldisc;
if (back)
back->provide_ldisc(backhandle, ldisc);
if (backend)
backend_provide_ldisc(backend, ldisc);
return ldisc;
}
@ -117,8 +115,8 @@ void ldisc_free(Ldisc *ldisc)
{
if (ldisc->term)
ldisc->term->ldisc = NULL;
if (ldisc->back)
ldisc->back->provide_ldisc(ldisc->backhandle, NULL);
if (ldisc->backend)
backend_provide_ldisc(ldisc->backend, NULL);
if (ldisc->buf)
sfree(ldisc->buf);
sfree(ldisc);
@ -219,7 +217,7 @@ void ldisc_send(Ldisc *ldisc, const void *vbuf, int len, int interactive)
bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1]));
ldisc->buflen--;
}
ldisc->back->special(ldisc->backhandle, TS_EL);
backend_special(ldisc->backend, TS_EL);
/*
* We don't send IP, SUSP or ABORT if the user has
* configured telnet specials off! This breaks
@ -228,11 +226,11 @@ void ldisc_send(Ldisc *ldisc, const void *vbuf, int len, int interactive)
if (!ldisc->telnet_keyboard)
goto default_case;
if (c == CTRL('C'))
ldisc->back->special(ldisc->backhandle, TS_IP);
backend_special(ldisc->backend, TS_IP);
if (c == CTRL('Z'))
ldisc->back->special(ldisc->backhandle, TS_SUSP);
backend_special(ldisc->backend, TS_SUSP);
if (c == CTRL('\\'))
ldisc->back->special(ldisc->backhandle, TS_ABORT);
backend_special(ldisc->backend, TS_ABORT);
break;
case CTRL('R'): /* redraw line */
if (ECHOING) {
@ -247,9 +245,9 @@ void ldisc_send(Ldisc *ldisc, const void *vbuf, int len, int interactive)
break;
case CTRL('D'): /* logout or send */
if (ldisc->buflen == 0) {
ldisc->back->special(ldisc->backhandle, TS_EOF);
backend_special(ldisc->backend, TS_EOF);
} else {
ldisc->back->send(ldisc->backhandle, ldisc->buf, ldisc->buflen);
backend_send(ldisc->backend, ldisc->buf, ldisc->buflen);
ldisc->buflen = 0;
}
break;
@ -285,13 +283,14 @@ void ldisc_send(Ldisc *ldisc, const void *vbuf, int len, int interactive)
/* FALLTHROUGH */
case KCTRL('M'): /* send with newline */
if (ldisc->buflen > 0)
ldisc->back->send(ldisc->backhandle, ldisc->buf, ldisc->buflen);
backend_send(ldisc->backend,
ldisc->buf, ldisc->buflen);
if (ldisc->protocol == PROT_RAW)
ldisc->back->send(ldisc->backhandle, "\r\n", 2);
backend_send(ldisc->backend, "\r\n", 2);
else if (ldisc->protocol == PROT_TELNET && ldisc->telnet_newline)
ldisc->back->special(ldisc->backhandle, TS_EOL);
backend_special(ldisc->backend, TS_EOL);
else
ldisc->back->send(ldisc->backhandle, "\r", 1);
backend_send(ldisc->backend, "\r", 1);
if (ECHOING)
c_write(ldisc, "\r\n", 2);
ldisc->buflen = 0;
@ -313,7 +312,7 @@ void ldisc_send(Ldisc *ldisc, const void *vbuf, int len, int interactive)
}
} else {
if (ldisc->buflen != 0) {
ldisc->back->send(ldisc->backhandle, ldisc->buf, ldisc->buflen);
backend_send(ldisc->backend, ldisc->buf, ldisc->buflen);
while (ldisc->buflen > 0) {
bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1]));
ldisc->buflen--;
@ -326,33 +325,33 @@ void ldisc_send(Ldisc *ldisc, const void *vbuf, int len, int interactive)
switch (buf[0]) {
case CTRL('M'):
if (ldisc->protocol == PROT_TELNET && ldisc->telnet_newline)
ldisc->back->special(ldisc->backhandle, TS_EOL);
backend_special(ldisc->backend, TS_EOL);
else
ldisc->back->send(ldisc->backhandle, "\r", 1);
backend_send(ldisc->backend, "\r", 1);
break;
case CTRL('?'):
case CTRL('H'):
if (ldisc->telnet_keyboard) {
ldisc->back->special(ldisc->backhandle, TS_EC);
backend_special(ldisc->backend, TS_EC);
break;
}
case CTRL('C'):
if (ldisc->telnet_keyboard) {
ldisc->back->special(ldisc->backhandle, TS_IP);
backend_special(ldisc->backend, TS_IP);
break;
}
case CTRL('Z'):
if (ldisc->telnet_keyboard) {
ldisc->back->special(ldisc->backhandle, TS_SUSP);
backend_special(ldisc->backend, TS_SUSP);
break;
}
default:
ldisc->back->send(ldisc->backhandle, buf, len);
backend_send(ldisc->backend, buf, len);
break;
}
} else
ldisc->back->send(ldisc->backhandle, buf, len);
backend_send(ldisc->backend, buf, len);
}
}
}

View File

@ -10,8 +10,7 @@
struct Ldisc_tag {
Terminal *term;
Backend *back;
void *backhandle;
Backend *backend;
void *frontend;
/*

View File

@ -9,8 +9,7 @@ struct pinger_tag {
int interval;
int pending;
unsigned long when_set, next;
Backend *back;
void *backhandle;
Backend *backend;
};
static void pinger_schedule(Pinger pinger);
@ -20,7 +19,7 @@ static void pinger_timer(void *ctx, unsigned long now)
Pinger pinger = (Pinger)ctx;
if (pinger->pending && now == pinger->next) {
pinger->back->special(pinger->backhandle, TS_PING);
backend_special(pinger->backend, TS_PING);
pinger->pending = FALSE;
pinger_schedule(pinger);
}
@ -45,14 +44,13 @@ static void pinger_schedule(Pinger pinger)
}
}
Pinger pinger_new(Conf *conf, Backend *back, void *backhandle)
Pinger pinger_new(Conf *conf, Backend *backend)
{
Pinger pinger = snew(struct pinger_tag);
pinger->interval = conf_get_int(conf, CONF_ping_interval);
pinger->pending = FALSE;
pinger->back = back;
pinger->backhandle = backhandle;
pinger->backend = backend;
pinger_schedule(pinger);
return pinger;

80
pscp.c
View File

@ -43,8 +43,7 @@ static int fallback_cmd_is_sftp = 0;
static int using_sftp = 0;
static int uploading = 0;
static Backend *back;
static void *backhandle;
static Backend *backend;
static Conf *conf;
int sent_eof = FALSE;
@ -247,7 +246,7 @@ static int ssh_scp_recv(void *buf, int len)
}
while (outlen > 0) {
if (back->exitcode(backhandle) >= 0 || ssh_sftp_loop_iteration() < 0)
if (backend_exitcode(backend) >= 0 || ssh_sftp_loop_iteration() < 0)
return 0; /* doom */
}
@ -259,8 +258,8 @@ static int ssh_scp_recv(void *buf, int len)
*/
static void ssh_scp_init(void)
{
while (!back->sendok(backhandle)) {
if (back->exitcode(backhandle) >= 0) {
while (!backend_sendok(backend)) {
if (backend_exitcode(backend) >= 0) {
errs++;
return;
}
@ -271,7 +270,7 @@ static void ssh_scp_init(void)
}
/* Work out which backend we ended up using. */
if (!ssh_fallback_cmd(backhandle))
if (!ssh_fallback_cmd(backend))
using_sftp = main_cmd_is_sftp;
else
using_sftp = fallback_cmd_is_sftp;
@ -300,9 +299,9 @@ static void bump(const char *fmt, ...)
sfree(str2);
errs++;
if (back != NULL && back->connected(backhandle)) {
if (backend && backend_connected(backend)) {
char ch;
back->special(backhandle, TS_EOF);
backend_special(backend, TS_EOF);
sent_eof = TRUE;
ssh_scp_recv(&ch, 1);
}
@ -498,21 +497,19 @@ static void do_cmd(char *host, char *user, char *cmd)
}
conf_set_int(conf, CONF_nopty, TRUE);
back = &ssh_backend;
logctx = log_init(NULL, conf);
console_provide_logctx(logctx);
platform_psftp_pre_conn_setup();
err = back->init(NULL, &backhandle, conf,
conf_get_str(conf, CONF_host),
conf_get_int(conf, CONF_port),
&realhost, 0,
conf_get_int(conf, CONF_tcp_keepalives));
err = backend_init(&ssh_backend, NULL, &backend, conf,
conf_get_str(conf, CONF_host),
conf_get_int(conf, CONF_port),
&realhost, 0,
conf_get_int(conf, CONF_tcp_keepalives));
if (err != NULL)
bump("ssh_init: %s", err);
back->provide_logctx(backhandle, logctx);
backend_provide_logctx(backend, logctx);
ssh_scp_init();
if (verbose && realhost != NULL && errs == 0)
tell_user(stderr, "Connected to %s", realhost);
@ -644,12 +641,12 @@ int sftp_recvdata(char *buf, int len)
}
int sftp_senddata(char *buf, int len)
{
back->send(backhandle, buf, len);
backend_send(backend, buf, len);
return 1;
}
int sftp_sendbuffer(void)
{
return back->sendbuffer(backhandle);
return backend_sendbuffer(backend);
}
/* ----------------------------------------------------------------------
@ -806,8 +803,8 @@ int scp_send_errmsg(char *str)
if (using_sftp) {
/* do nothing; we never need to send our errors to the server */
} else {
back->send(backhandle, "\001", 1);/* scp protocol error prefix */
back->send(backhandle, str, strlen(str));
backend_send(backend, "\001", 1);/* scp protocol error prefix */
backend_send(backend, str, strlen(str));
}
return 0; /* can't fail */
}
@ -822,7 +819,7 @@ int scp_send_filetimes(unsigned long mtime, unsigned long atime)
} else {
char buf[80];
sprintf(buf, "T%lu 0 %lu 0\n", mtime, atime);
back->send(backhandle, buf, strlen(buf));
backend_send(backend, buf, strlen(buf));
return response();
}
}
@ -869,9 +866,9 @@ int scp_send_filename(const char *name, uint64 size, int permissions)
if (permissions < 0)
permissions = 0644;
sprintf(buf, "C%04o %s ", (int)(permissions & 07777), sizestr);
back->send(backhandle, buf, strlen(buf));
back->send(backhandle, name, strlen(name));
back->send(backhandle, "\n", 1);
backend_send(backend, buf, strlen(buf));
backend_send(backend, name, strlen(name));
backend_send(backend, "\n", 1);
return response();
}
}
@ -903,7 +900,7 @@ int scp_send_filedata(char *data, int len)
scp_sftp_fileoffset = uint64_add32(scp_sftp_fileoffset, len);
return 0;
} else {
int bufsize = back->send(backhandle, data, len);
int bufsize = backend_send(backend, data, len);
/*
* If the network transfer is backing up - that is, the
@ -914,7 +911,7 @@ int scp_send_filedata(char *data, int len)
while (bufsize > MAX_SCP_BUFSIZE) {
if (ssh_sftp_loop_iteration() < 0)
return 1;
bufsize = back->sendbuffer(backhandle);
bufsize = backend_sendbuffer(backend);
}
return 0;
@ -963,7 +960,7 @@ int scp_send_finish(void)
scp_has_times = 0;
return 0;
} else {
back->send(backhandle, "", 1);
backend_send(backend, "", 1);
return response();
}
}
@ -1033,9 +1030,9 @@ int scp_send_dirname(const char *name, int modes)
} else {
char buf[40];
sprintf(buf, "D%04o 0 ", modes);
back->send(backhandle, buf, strlen(buf));
back->send(backhandle, name, strlen(name));
back->send(backhandle, "\n", 1);
backend_send(backend, buf, strlen(buf));
backend_send(backend, name, strlen(name));
backend_send(backend, "\n", 1);
return response();
}
}
@ -1046,7 +1043,7 @@ int scp_send_enddir(void)
sfree(scp_sftp_remotepath);
return 0;
} else {
back->send(backhandle, "E\n", 2);
backend_send(backend, "E\n", 2);
return response();
}
}
@ -1144,7 +1141,7 @@ int scp_sink_setup(const char *source, int preserve, int recursive)
int scp_sink_init(void)
{
if (!using_sftp) {
back->send(backhandle, "", 1);
backend_send(backend, "", 1);
}
return 0;
}
@ -1457,14 +1454,14 @@ int scp_get_sink_action(struct scp_sink_action *act)
case '\02': /* fatal error */
bump("%s", act->buf);
case 'E':
back->send(backhandle, "", 1);
backend_send(backend, "", 1);
act->action = SCP_SINK_ENDDIR;
return 0;
case 'T':
if (sscanf(act->buf, "%lu %*d %lu %*d",
&act->mtime, &act->atime) == 2) {
act->settime = 1;
back->send(backhandle, "", 1);
backend_send(backend, "", 1);
continue; /* go round again */
}
bump("Protocol error: Illegal time format");
@ -1521,7 +1518,7 @@ int scp_accept_filexfer(void)
sfree(scp_sftp_currentname);
return 0;
} else {
back->send(backhandle, "", 1);
backend_send(backend, "", 1);
return 0; /* can't fail */
}
}
@ -1606,7 +1603,7 @@ int scp_finish_filerecv(void)
fxp_close_recv(pktin, req);
return 0;
} else {
back->send(backhandle, "", 1);
backend_send(backend, "", 1);
return response();
}
}
@ -2355,7 +2352,7 @@ int psftp_main(int argc, char *argv[])
}
argc -= i;
argv += i;
back = NULL;
backend = NULL;
if (list) {
if (argc != 1)
@ -2375,9 +2372,9 @@ int psftp_main(int argc, char *argv[])
tolocal(argc, argv);
}
if (back != NULL && back->connected(backhandle)) {
if (backend && backend_connected(backend)) {
char ch;
back->special(backhandle, TS_EOF);
backend_special(backend, TS_EOF);
sent_eof = TRUE;
ssh_scp_recv(&ch, 1);
}
@ -2385,9 +2382,8 @@ int psftp_main(int argc, char *argv[])
cmdline_cleanup();
console_provide_logctx(NULL);
back->free(backhandle);
backhandle = NULL;
back = NULL;
backend_free(backend);
backend = NULL;
sk_cleanup();
return (errs == 0 ? 0 : 1);
}

74
psftp.c
View File

@ -34,8 +34,7 @@ void do_sftp_cleanup();
*/
char *pwd, *homedir;
static Backend *back;
static void *backhandle;
static Backend *backend;
static Conf *conf;
int sent_eof = FALSE;
@ -967,14 +966,14 @@ int sftp_cmd_quit(struct sftp_command *cmd)
int sftp_cmd_close(struct sftp_command *cmd)
{
if (back == NULL) {
if (!backend) {
not_connected();
return 0;
}
if (back != NULL && back->connected(backhandle)) {
if (backend_connected(backend)) {
char ch;
back->special(backhandle, TS_EOF);
backend_special(backend, TS_EOF);
sent_eof = TRUE;
sftp_recvdata(&ch, 1);
}
@ -999,7 +998,7 @@ int sftp_cmd_ls(struct sftp_command *cmd)
struct sftp_request *req;
int i;
if (back == NULL) {
if (!backend) {
not_connected();
return 0;
}
@ -1123,7 +1122,7 @@ int sftp_cmd_cd(struct sftp_command *cmd)
struct sftp_request *req;
char *dir;
if (back == NULL) {
if (!backend) {
not_connected();
return 0;
}
@ -1164,7 +1163,7 @@ int sftp_cmd_cd(struct sftp_command *cmd)
*/
int sftp_cmd_pwd(struct sftp_command *cmd)
{
if (back == NULL) {
if (!backend) {
not_connected();
return 0;
}
@ -1188,7 +1187,7 @@ int sftp_general_get(struct sftp_command *cmd, int restart, int multiple)
int i, ret;
int recurse = FALSE;
if (back == NULL) {
if (!backend) {
not_connected();
return 0;
}
@ -1304,7 +1303,7 @@ int sftp_general_put(struct sftp_command *cmd, int restart, int multiple)
int i, ret;
int recurse = FALSE;
if (back == NULL) {
if (!backend) {
not_connected();
return 0;
}
@ -1405,7 +1404,7 @@ int sftp_cmd_mkdir(struct sftp_command *cmd)
int result;
int i, ret;
if (back == NULL) {
if (!backend) {
not_connected();
return 0;
}
@ -1463,7 +1462,7 @@ int sftp_cmd_rmdir(struct sftp_command *cmd)
{
int i, ret;
if (back == NULL) {
if (!backend) {
not_connected();
return 0;
}
@ -1504,7 +1503,7 @@ int sftp_cmd_rm(struct sftp_command *cmd)
{
int i, ret;
if (back == NULL) {
if (!backend) {
not_connected();
return 0;
}
@ -1597,7 +1596,7 @@ int sftp_cmd_mv(struct sftp_command *cmd)
struct sftp_context_mv actx, *ctx = &actx;
int i, ret;
if (back == NULL) {
if (!backend) {
not_connected();
return 0;
}
@ -1689,7 +1688,7 @@ int sftp_cmd_chmod(struct sftp_command *cmd)
int i, ret;
struct sftp_context_chmod actx, *ctx = &actx;
if (back == NULL) {
if (!backend) {
not_connected();
return 0;
}
@ -1815,7 +1814,7 @@ static int sftp_cmd_open(struct sftp_command *cmd)
{
int portnumber;
if (back != NULL) {
if (backend) {
printf("psftp: already connected\n");
return 0;
}
@ -1835,7 +1834,7 @@ static int sftp_cmd_open(struct sftp_command *cmd)
portnumber = 0;
if (psftp_connect(cmd->words[1], NULL, portnumber)) {
back = NULL; /* connection is already closed */
backend = NULL; /* connection is already closed */
return -1; /* this is fatal */
}
do_sftp_init();
@ -2214,7 +2213,7 @@ struct sftp_command *sftp_getcmd(FILE *fp, int mode, int modeflags)
printf("psftp> ");
line = fgetline(fp);
} else {
line = ssh_sftp_get_cmdline("psftp> ", back == NULL);
line = ssh_sftp_get_cmdline("psftp> ", !backend);
}
if (!line || !*line) {
@ -2355,14 +2354,13 @@ static int do_sftp_init(void)
void do_sftp_cleanup()
{
char ch;
if (back) {
back->special(backhandle, TS_EOF);
if (backend) {
backend_special(backend, TS_EOF);
sent_eof = TRUE;
sftp_recvdata(&ch, 1);
back->free(backhandle);
backend_free(backend);
sftp_cleanup_request();
back = NULL;
backhandle = NULL;
backend = NULL;
}
if (pwd) {
sfree(pwd);
@ -2602,7 +2600,7 @@ int sftp_recvdata(char *buf, int len)
}
while (outlen > 0) {
if (back->exitcode(backhandle) >= 0 || ssh_sftp_loop_iteration() < 0)
if (backend_exitcode(backend) >= 0 || ssh_sftp_loop_iteration() < 0)
return 0; /* doom */
}
@ -2610,12 +2608,12 @@ int sftp_recvdata(char *buf, int len)
}
int sftp_senddata(char *buf, int len)
{
back->send(backhandle, buf, len);
backend_send(backend, buf, len);
return 1;
}
int sftp_sendbuffer(void)
{
return back->sendbuffer(backhandle);
return backend_sendbuffer(backend);
}
/*
@ -2826,25 +2824,23 @@ static int psftp_connect(char *userhost, char *user, int portnumber)
"exec sftp-server");
conf_set_int(conf, CONF_ssh_subsys2, FALSE);
back = &ssh_backend;
logctx = log_init(NULL, conf);
console_provide_logctx(logctx);
platform_psftp_pre_conn_setup();
err = back->init(NULL, &backhandle, conf,
conf_get_str(conf, CONF_host),
conf_get_int(conf, CONF_port),
&realhost, 0,
conf_get_int(conf, CONF_tcp_keepalives));
err = backend_init(&ssh_backend, NULL, &backend, conf,
conf_get_str(conf, CONF_host),
conf_get_int(conf, CONF_port),
&realhost, 0,
conf_get_int(conf, CONF_tcp_keepalives));
if (err != NULL) {
fprintf(stderr, "ssh_init: %s\n", err);
return 1;
}
back->provide_logctx(backhandle, logctx);
while (!back->sendok(backhandle)) {
if (back->exitcode(backhandle) >= 0)
backend_provide_logctx(backend, logctx);
while (!backend_sendok(backend)) {
if (backend_exitcode(backend) >= 0)
return 1;
if (ssh_sftp_loop_iteration() < 0) {
fprintf(stderr, "ssh_init: error during SSH connection setup\n");
@ -2945,7 +2941,7 @@ int psftp_main(int argc, char *argv[])
}
argc -= i;
argv += i;
back = NULL;
backend = NULL;
/*
* If the loaded session provides a hostname, and a hostname has not
@ -2975,9 +2971,9 @@ int psftp_main(int argc, char *argv[])
ret = do_sftp(mode, modeflags, batchfile);
if (back != NULL && back->connected(backhandle)) {
if (backend && backend_connected(backend)) {
char ch;
back->special(backhandle, TS_EOF);
backend_special(backend, TS_EOF);
sent_eof = TRUE;
sftp_recvdata(&ch, 1);
}

102
putty.h
View File

@ -441,43 +441,67 @@ enum {
ADDRTYPE_UNSPEC, ADDRTYPE_IPV4, ADDRTYPE_IPV6, ADDRTYPE_NAME
};
struct backend_tag {
const char *(*init) (void *frontend_handle, void **backend_handle,
struct Backend {
const Backend_vtable *vt;
};
struct Backend_vtable {
const char *(*init) (void *frontend_handle, Backend **backend_out,
Conf *conf, const char *host, int port,
char **realhost, int nodelay, int keepalive);
void (*free) (void *handle);
/* back->reconfig() passes in a replacement configuration. */
void (*reconfig) (void *handle, Conf *conf);
/* back->send() returns the current amount of buffered data. */
int (*send) (void *handle, const char *buf, int len);
/* back->sendbuffer() does the same thing but without attempting a send */
int (*sendbuffer) (void *handle);
void (*size) (void *handle, int width, int height);
void (*special) (void *handle, Telnet_Special code);
const struct telnet_special *(*get_specials) (void *handle);
int (*connected) (void *handle);
int (*exitcode) (void *handle);
/* If back->sendok() returns FALSE, data sent to it from the frontend
* may be lost. */
int (*sendok) (void *handle);
int (*ldisc) (void *handle, int);
void (*provide_ldisc) (void *handle, Ldisc *ldisc);
void (*provide_logctx) (void *handle, LogContext *logctx);
/*
* back->unthrottle() tells the back end that the front end
* buffer is clearing.
*/
void (*unthrottle) (void *handle, int);
int (*cfg_info) (void *handle);
void (*free) (Backend *be);
/* Pass in a replacement configuration. */
void (*reconfig) (Backend *be, Conf *conf);
/* send() returns the current amount of buffered data. */
int (*send) (Backend *be, const char *buf, int len);
/* sendbuffer() does the same thing but without attempting a send */
int (*sendbuffer) (Backend *be);
void (*size) (Backend *be, int width, int height);
void (*special) (Backend *be, Telnet_Special code);
const struct telnet_special *(*get_specials) (Backend *be);
int (*connected) (Backend *be);
int (*exitcode) (Backend *be);
/* If back->sendok() returns FALSE, the backend doesn't currently
* want input data, so the frontend should avoid acquiring any if
* possible (passing back-pressure on to its sender). */
int (*sendok) (Backend *be);
int (*ldisc_option_state) (Backend *be, int);
void (*provide_ldisc) (Backend *be, Ldisc *ldisc);
void (*provide_logctx) (Backend *be, LogContext *logctx);
/* Tells the back end that the front end buffer is clearing. */
void (*unthrottle) (Backend *be, int bufsize);
int (*cfg_info) (Backend *be);
/* Only implemented in the SSH protocol: check whether a
* connection-sharing upstream exists for a given configuration. */
int (*test_for_upstream)(const char *host, int port, Conf *conf);
const char *name;
int protocol;
int default_port;
};
extern Backend *backends[];
#define backend_init(vt, fe, out, conf, host, port, rhost, nd, ka) \
((vt)->init(fe, out, conf, host, port, rhost, nd, ka))
#define backend_free(be) ((be)->vt->free(be))
#define backend_reconfig(be, conf) ((be)->vt->reconfig(be, conf))
#define backend_send(be, buf, len) ((be)->vt->send(be, buf, len))
#define backend_sendbuffer(be) ((be)->vt->sendbuffer(be))
#define backend_size(be, w, h) ((be)->vt->size(be, w, h))
#define backend_special(be, code) ((be)->vt->special(be, code))
#define backend_get_specials(be) ((be)->vt->get_specials(be))
#define backend_connected(be) ((be)->vt->connected(be))
#define backend_exitcode(be) ((be)->vt->exitcode(be))
#define backend_sendok(be) ((be)->vt->sendok(be))
#define backend_ldisc_option_state(be, opt) \
((be)->vt->ldisc_option_state(be, opt))
#define backend_provide_ldisc(be, ldisc) ((be)->vt->provide_ldisc(be, ldisc))
#define backend_provide_logctx(be, logctx) \
((be)->vt->provide_logctx(be, logctx))
#define backend_unthrottle(be, bufsize) ((be)->vt->unthrottle(be, bufsize))
#define backend_cfg_info(be) ((be)->vt->cfg_info(be))
extern const struct Backend_vtable *const backends[];
/*
* Suggested default protocol provided by the backend link module.
@ -1046,8 +1070,8 @@ void random_destroy_seed(void);
/*
* Exports from settings.c.
*/
Backend *backend_from_name(const char *name);
Backend *backend_from_proto(int proto);
const struct Backend_vtable *backend_vt_from_name(const char *name);
const struct Backend_vtable *backend_vt_from_proto(int proto);
char *get_remote_username(Conf *conf); /* dynamically allocated */
char *save_settings(const char *section, Conf *conf);
void save_open_settings(void *sesskey, Conf *conf);
@ -1107,9 +1131,7 @@ void term_request_paste(Terminal *, int clipboard);
void term_seen_key_event(Terminal *);
int term_data(Terminal *, int is_stderr, const void *data, int len);
int term_data_untrusted(Terminal *, const void *data, int len);
void term_provide_resize_fn(Terminal *term,
void (*resize_fn)(void *, int, int),
void *resize_ctx);
void term_provide_backend(Terminal *term, Backend *backend);
void term_provide_logctx(Terminal *term, LogContext *logctx);
void term_set_focus(Terminal *term, int has_focus);
char *term_get_ttymode(Terminal *term, const char *mode);
@ -1145,36 +1167,36 @@ void log_packet(LogContext *logctx, int direction, int type,
* Exports from testback.c
*/
extern Backend null_backend;
extern Backend loop_backend;
extern const struct Backend_vtable null_backend;
extern const struct Backend_vtable loop_backend;
/*
* Exports from raw.c.
*/
extern Backend raw_backend;
extern const struct Backend_vtable raw_backend;
/*
* Exports from rlogin.c.
*/
extern Backend rlogin_backend;
extern const struct Backend_vtable rlogin_backend;
/*
* Exports from telnet.c.
*/
extern Backend telnet_backend;
extern const struct Backend_vtable telnet_backend;
/*
* Exports from ssh.c.
*/
extern Backend ssh_backend;
extern const struct Backend_vtable ssh_backend;
/*
* Exports from ldisc.c.
*/
Ldisc *ldisc_create(Conf *, Terminal *, Backend *, void *, void *);
Ldisc *ldisc_create(Conf *, Terminal *, Backend *, void *);
void ldisc_configure(Ldisc *, Conf *);
void ldisc_free(Ldisc *);
void ldisc_send(Ldisc *, const void *buf, int len, int interactive);
@ -1205,7 +1227,7 @@ void random_unref(void);
* Exports from pinger.c.
*/
typedef struct pinger_tag *Pinger;
Pinger pinger_new(Conf *conf, Backend *back, void *backhandle);
Pinger pinger_new(Conf *conf, Backend *backend);
void pinger_reconfig(Pinger, Conf *oldconf, Conf *newconf);
void pinger_free(Pinger);

54
raw.c
View File

@ -20,9 +20,10 @@ typedef struct raw_backend_data {
Conf *conf;
const Plug_vtable *plugvt;
Backend backend;
} *Raw;
static void raw_size(void *handle, int width, int height);
static void raw_size(Backend *be, int width, int height);
static void c_write(Raw raw, const void *buf, int len)
{
@ -116,7 +117,7 @@ static const Plug_vtable Raw_plugvt = {
* Also places the canonical host name into `realhost'. It must be
* freed by the caller.
*/
static const char *raw_init(void *frontend_handle, void **backend_handle,
static const char *raw_init(void *frontend_handle, Backend **backend_handle,
Conf *conf,
const char *host, int port, char **realhost,
int nodelay, int keepalive)
@ -129,9 +130,10 @@ static const char *raw_init(void *frontend_handle, void **backend_handle,
raw = snew(struct raw_backend_data);
raw->plugvt = &Raw_plugvt;
raw->backend.vt = &raw_backend;
raw->s = NULL;
raw->closed_on_socket_error = FALSE;
*backend_handle = raw;
*backend_handle = &raw->backend;
raw->sent_console_eof = raw->sent_socket_eof = FALSE;
raw->bufsize = 0;
raw->session_started = FALSE;
@ -176,9 +178,9 @@ static const char *raw_init(void *frontend_handle, void **backend_handle,
return NULL;
}
static void raw_free(void *handle)
static void raw_free(Backend *be)
{
Raw raw = (Raw) handle;
Raw raw = FROMFIELD(be, struct raw_backend_data, backend);
if (raw->s)
sk_close(raw->s);
@ -189,16 +191,16 @@ static void raw_free(void *handle)
/*
* Stub routine (we don't have any need to reconfigure this backend).
*/
static void raw_reconfig(void *handle, Conf *conf)
static void raw_reconfig(Backend *be, Conf *conf)
{
}
/*
* Called to send data down the raw connection.
*/
static int raw_send(void *handle, const char *buf, int len)
static int raw_send(Backend *be, const char *buf, int len)
{
Raw raw = (Raw) handle;
Raw raw = FROMFIELD(be, struct raw_backend_data, backend);
if (raw->s == NULL)
return 0;
@ -211,16 +213,16 @@ static int raw_send(void *handle, const char *buf, int len)
/*
* Called to query the current socket sendability status.
*/
static int raw_sendbuffer(void *handle)
static int raw_sendbuffer(Backend *be)
{
Raw raw = (Raw) handle;
Raw raw = FROMFIELD(be, struct raw_backend_data, backend);
return raw->bufsize;
}
/*
* Called to set the size of the window
*/
static void raw_size(void *handle, int width, int height)
static void raw_size(Backend *be, int width, int height)
{
/* Do nothing! */
return;
@ -229,9 +231,9 @@ static void raw_size(void *handle, int width, int height)
/*
* Send raw special codes. We only handle outgoing EOF here.
*/
static void raw_special(void *handle, Telnet_Special code)
static void raw_special(Backend *be, Telnet_Special code)
{
Raw raw = (Raw) handle;
Raw raw = FROMFIELD(be, struct raw_backend_data, backend);
if (code == TS_EOF && raw->s) {
sk_write_eof(raw->s);
raw->sent_socket_eof= TRUE;
@ -245,48 +247,48 @@ static void raw_special(void *handle, Telnet_Special code)
* Return a list of the special codes that make sense in this
* protocol.
*/
static const struct telnet_special *raw_get_specials(void *handle)
static const struct telnet_special *raw_get_specials(Backend *be)
{
return NULL;
}
static int raw_connected(void *handle)
static int raw_connected(Backend *be)
{
Raw raw = (Raw) handle;
Raw raw = FROMFIELD(be, struct raw_backend_data, backend);
return raw->s != NULL;
}
static int raw_sendok(void *handle)
static int raw_sendok(Backend *be)
{
return 1;
}
static void raw_unthrottle(void *handle, int backlog)
static void raw_unthrottle(Backend *be, int backlog)
{
Raw raw = (Raw) handle;
Raw raw = FROMFIELD(be, struct raw_backend_data, backend);
sk_set_frozen(raw->s, backlog > RAW_MAX_BACKLOG);
}
static int raw_ldisc(void *handle, int option)
static int raw_ldisc(Backend *be, int option)
{
if (option == LD_EDIT || option == LD_ECHO)
return 1;
return 0;
}
static void raw_provide_ldisc(void *handle, Ldisc *ldisc)
static void raw_provide_ldisc(Backend *be, Ldisc *ldisc)
{
/* This is a stub. */
}
static void raw_provide_logctx(void *handle, LogContext *logctx)
static void raw_provide_logctx(Backend *be, LogContext *logctx)
{
/* This is a stub. */
}
static int raw_exitcode(void *handle)
static int raw_exitcode(Backend *be)
{
Raw raw = (Raw) handle;
Raw raw = FROMFIELD(be, struct raw_backend_data, backend);
if (raw->s != NULL)
return -1; /* still connected */
else if (raw->closed_on_socket_error)
@ -299,12 +301,12 @@ static int raw_exitcode(void *handle)
/*
* cfg_info for Raw does nothing at all.
*/
static int raw_cfg_info(void *handle)
static int raw_cfg_info(Backend *be)
{
return 0;
}
Backend raw_backend = {
const struct Backend_vtable raw_backend = {
raw_init,
raw_free,
raw_reconfig,

View File

@ -26,10 +26,9 @@ typedef struct rlogin_tag {
prompts_t *prompt;
const Plug_vtable *plugvt;
Backend backend;
} *Rlogin;
static void rlogin_size(void *handle, int width, int height);
static void c_write(Rlogin rlogin, const void *buf, int len)
{
int backlog = from_backend(rlogin->frontend, 0, buf, len);
@ -80,7 +79,8 @@ static void rlogin_receive(Plug plug, int urgent, char *data, int len)
len--;
if (c == '\x80') {
rlogin->cansize = 1;
rlogin_size(rlogin, rlogin->term_width, rlogin->term_height);
backend_size(&rlogin->backend,
rlogin->term_width, rlogin->term_height);
}
/*
* We should flush everything (aka Telnet SYNCH) if we see
@ -148,7 +148,7 @@ static const Plug_vtable Rlogin_plugvt = {
* Also places the canonical host name into `realhost'. It must be
* freed by the caller.
*/
static const char *rlogin_init(void *frontend_handle, void **backend_handle,
static const char *rlogin_init(void *frontend_handle, Backend **backend_handle,
Conf *conf,
const char *host, int port, char **realhost,
int nodelay, int keepalive)
@ -162,6 +162,7 @@ static const char *rlogin_init(void *frontend_handle, void **backend_handle,
rlogin = snew(struct rlogin_tag);
rlogin->plugvt = &Rlogin_plugvt;
rlogin->backend.vt = &rlogin_backend;
rlogin->s = NULL;
rlogin->closed_on_socket_error = FALSE;
rlogin->frontend = frontend_handle;
@ -171,7 +172,7 @@ static const char *rlogin_init(void *frontend_handle, void **backend_handle,
rlogin->cansize = 0;
rlogin->prompt = NULL;
rlogin->conf = conf_copy(conf);
*backend_handle = rlogin;
*backend_handle = &rlogin->backend;
addressfamily = conf_get_int(conf, CONF_addressfamily);
/*
@ -232,9 +233,9 @@ static const char *rlogin_init(void *frontend_handle, void **backend_handle,
return NULL;
}
static void rlogin_free(void *handle)
static void rlogin_free(Backend *be)
{
Rlogin rlogin = (Rlogin) handle;
Rlogin rlogin = FROMFIELD(be, struct rlogin_tag, backend);
if (rlogin->prompt)
free_prompts(rlogin->prompt);
@ -247,16 +248,16 @@ static void rlogin_free(void *handle)
/*
* Stub routine (we don't have any need to reconfigure this backend).
*/
static void rlogin_reconfig(void *handle, Conf *conf)
static void rlogin_reconfig(Backend *be, Conf *conf)
{
}
/*
* Called to send data down the rlogin connection.
*/
static int rlogin_send(void *handle, const char *buf, int len)
static int rlogin_send(Backend *be, const char *buf, int len)
{
Rlogin rlogin = (Rlogin) handle;
Rlogin rlogin = FROMFIELD(be, struct rlogin_tag, backend);
bufchain bc;
if (rlogin->s == NULL)
@ -296,18 +297,18 @@ static int rlogin_send(void *handle, const char *buf, int len)
/*
* Called to query the current socket sendability status.
*/
static int rlogin_sendbuffer(void *handle)
static int rlogin_sendbuffer(Backend *be)
{
Rlogin rlogin = (Rlogin) handle;
Rlogin rlogin = FROMFIELD(be, struct rlogin_tag, backend);
return rlogin->bufsize;
}
/*
* Called to set the size of the window
*/
static void rlogin_size(void *handle, int width, int height)
static void rlogin_size(Backend *be, int width, int height)
{
Rlogin rlogin = (Rlogin) handle;
Rlogin rlogin = FROMFIELD(be, struct rlogin_tag, backend);
char b[12] = { '\xFF', '\xFF', 0x73, 0x73, 0, 0, 0, 0, 0, 0, 0, 0 };
rlogin->term_width = width;
@ -327,7 +328,7 @@ static void rlogin_size(void *handle, int width, int height)
/*
* Send rlogin special codes.
*/
static void rlogin_special(void *handle, Telnet_Special code)
static void rlogin_special(Backend *be, Telnet_Special code)
{
/* Do nothing! */
return;
@ -337,48 +338,48 @@ static void rlogin_special(void *handle, Telnet_Special code)
* Return a list of the special codes that make sense in this
* protocol.
*/
static const struct telnet_special *rlogin_get_specials(void *handle)
static const struct telnet_special *rlogin_get_specials(Backend *be)
{
return NULL;
}
static int rlogin_connected(void *handle)
static int rlogin_connected(Backend *be)
{
Rlogin rlogin = (Rlogin) handle;
Rlogin rlogin = FROMFIELD(be, struct rlogin_tag, backend);
return rlogin->s != NULL;
}
static int rlogin_sendok(void *handle)
static int rlogin_sendok(Backend *be)
{
/* Rlogin rlogin = (Rlogin) handle; */
/* Rlogin rlogin = FROMFIELD(be, struct rlogin_tag, backend); */
return 1;
}
static void rlogin_unthrottle(void *handle, int backlog)
static void rlogin_unthrottle(Backend *be, int backlog)
{
Rlogin rlogin = (Rlogin) handle;
Rlogin rlogin = FROMFIELD(be, struct rlogin_tag, backend);
sk_set_frozen(rlogin->s, backlog > RLOGIN_MAX_BACKLOG);
}
static int rlogin_ldisc(void *handle, int option)
static int rlogin_ldisc(Backend *be, int option)
{
/* Rlogin rlogin = (Rlogin) handle; */
/* Rlogin rlogin = FROMFIELD(be, struct rlogin_tag, backend); */
return 0;
}
static void rlogin_provide_ldisc(void *handle, Ldisc *ldisc)
static void rlogin_provide_ldisc(Backend *be, Ldisc *ldisc)
{
/* This is a stub. */
}
static void rlogin_provide_logctx(void *handle, LogContext *logctx)
static void rlogin_provide_logctx(Backend *be, LogContext *logctx)
{
/* This is a stub. */
}
static int rlogin_exitcode(void *handle)
static int rlogin_exitcode(Backend *be)
{
Rlogin rlogin = (Rlogin) handle;
Rlogin rlogin = FROMFIELD(be, struct rlogin_tag, backend);
if (rlogin->s != NULL)
return -1; /* still connected */
else if (rlogin->closed_on_socket_error)
@ -391,12 +392,12 @@ static int rlogin_exitcode(void *handle)
/*
* cfg_info for rlogin does nothing at all.
*/
static int rlogin_cfg_info(void *handle)
static int rlogin_cfg_info(Backend *be)
{
return 0;
}
Backend rlogin_backend = {
const struct Backend_vtable rlogin_backend = {
rlogin_init,
rlogin_free,
rlogin_reconfig,

View File

@ -74,18 +74,18 @@ const char *const ttymodes[] = {
* (which is only present in tools that manage settings).
*/
Backend *backend_from_name(const char *name)
const struct Backend_vtable *backend_vt_from_name(const char *name)
{
Backend **p;
const struct Backend_vtable *const *p;
for (p = backends; *p != NULL; p++)
if (!strcmp((*p)->name, name))
return *p;
return NULL;
}
Backend *backend_from_proto(int proto)
const struct Backend_vtable *backend_vt_from_proto(int proto)
{
Backend **p;
const struct Backend_vtable *const *p;
for (p = backends; *p != NULL; p++)
if ((*p)->protocol == proto)
return *p;
@ -528,9 +528,10 @@ void save_open_settings(void *sesskey, Conf *conf)
write_setting_i(sesskey, "SSHLogOmitData", conf_get_int(conf, CONF_logomitdata));
p = "raw";
{
const Backend *b = backend_from_proto(conf_get_int(conf, CONF_protocol));
if (b)
p = b->name;
const struct Backend_vtable *vt =
backend_vt_from_proto(conf_get_int(conf, CONF_protocol));
if (vt)
p = vt->name;
}
write_setting_s(sesskey, "Protocol", p);
write_setting_i(sesskey, "PortNumber", conf_get_int(conf, CONF_port));
@ -791,9 +792,9 @@ void load_open_settings(void *sesskey, Conf *conf)
conf_set_int(conf, CONF_protocol, default_protocol);
conf_set_int(conf, CONF_port, default_port);
{
const Backend *b = backend_from_name(prot);
if (b) {
conf_set_int(conf, CONF_protocol, b->protocol);
const struct Backend_vtable *vt = backend_vt_from_name(prot);
if (vt) {
conf_set_int(conf, CONF_protocol, vt->protocol);
gppi(sesskey, "PortNumber", default_port, conf, CONF_port);
}
}

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,

2
ssh.h
View File

@ -629,7 +629,7 @@ extern const char sshver[];
* 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 *backend);
void SHATransform(word32 * digest, word32 * data);

View File

@ -117,8 +117,6 @@ static const char *telopt(int opt)
#undef telnet_str
}
static void telnet_size(void *handle, int width, int height);
struct Opt {
int send; /* what we initially send */
int nsend; /* -ve send if requested to stop it */
@ -199,6 +197,7 @@ typedef struct telnet_tag {
Pinger pinger;
const Plug_vtable *plugvt;
Backend backend;
} *Telnet;
#define TELNET_MAX_BACKLOG 4096
@ -280,7 +279,8 @@ static void option_side_effects(Telnet telnet, const struct Opt *o, int enabled)
static void activate_option(Telnet telnet, const struct Opt *o)
{
if (o->send == WILL && o->option == TELOPT_NAWS)
telnet_size(telnet, telnet->term_width, telnet->term_height);
backend_size(&telnet->backend,
telnet->term_width, telnet->term_height);
if (o->send == WILL &&
(o->option == TELOPT_NEW_ENVIRON ||
o->option == TELOPT_OLD_ENVIRON)) {
@ -705,7 +705,7 @@ static const Plug_vtable Telnet_plugvt = {
* Also places the canonical host name into `realhost'. It must be
* freed by the caller.
*/
static const char *telnet_init(void *frontend_handle, void **backend_handle,
static const char *telnet_init(void *frontend_handle, Backend **backend_handle,
Conf *conf, const char *host, int port,
char **realhost, int nodelay, int keepalive)
{
@ -717,6 +717,7 @@ static const char *telnet_init(void *frontend_handle, void **backend_handle,
telnet = snew(struct telnet_tag);
telnet->plugvt = &Telnet_plugvt;
telnet->backend.vt = &telnet_backend;
telnet->conf = conf_copy(conf);
telnet->s = NULL;
telnet->closed_on_socket_error = FALSE;
@ -732,7 +733,7 @@ static const char *telnet_init(void *frontend_handle, void **backend_handle,
telnet->ldisc = NULL;
telnet->pinger = NULL;
telnet->session_started = TRUE;
*backend_handle = telnet;
*backend_handle = &telnet->backend;
/*
* Try to find host.
@ -756,7 +757,7 @@ static const char *telnet_init(void *frontend_handle, void **backend_handle,
if ((err = sk_socket_error(telnet->s)) != NULL)
return err;
telnet->pinger = pinger_new(telnet->conf, &telnet_backend, telnet);
telnet->pinger = pinger_new(telnet->conf, &telnet->backend);
/*
* Initialise option states.
@ -805,9 +806,9 @@ static const char *telnet_init(void *frontend_handle, void **backend_handle,
return NULL;
}
static void telnet_free(void *handle)
static void telnet_free(Backend *be)
{
Telnet telnet = (Telnet) handle;
Telnet telnet = FROMFIELD(be, struct telnet_tag, backend);
sfree(telnet->sb_buf);
if (telnet->s)
@ -822,9 +823,9 @@ static void telnet_free(void *handle)
* necessary, in this backend: we just save the fresh config for
* any subsequent negotiations.
*/
static void telnet_reconfig(void *handle, Conf *conf)
static void telnet_reconfig(Backend *be, Conf *conf)
{
Telnet telnet = (Telnet) handle;
Telnet telnet = FROMFIELD(be, struct telnet_tag, backend);
pinger_reconfig(telnet->pinger, telnet->conf, conf);
conf_free(telnet->conf);
telnet->conf = conf_copy(conf);
@ -833,9 +834,9 @@ static void telnet_reconfig(void *handle, Conf *conf)
/*
* Called to send data down the Telnet connection.
*/
static int telnet_send(void *handle, const char *buf, int len)
static int telnet_send(Backend *be, const char *buf, int len)
{
Telnet telnet = (Telnet) handle;
Telnet telnet = FROMFIELD(be, struct telnet_tag, backend);
unsigned char *p, *end;
static const unsigned char iac[2] = { IAC, IAC };
static const unsigned char cr[2] = { CR, NUL };
@ -868,18 +869,18 @@ static int telnet_send(void *handle, const char *buf, int len)
/*
* Called to query the current socket sendability status.
*/
static int telnet_sendbuffer(void *handle)
static int telnet_sendbuffer(Backend *be)
{
Telnet telnet = (Telnet) handle;
Telnet telnet = FROMFIELD(be, struct telnet_tag, backend);
return telnet->bufsize;
}
/*
* Called to set the size of the window from Telnet's POV.
*/
static void telnet_size(void *handle, int width, int height)
static void telnet_size(Backend *be, int width, int height)
{
Telnet telnet = (Telnet) handle;
Telnet telnet = FROMFIELD(be, struct telnet_tag, backend);
unsigned char b[24];
int n;
char *logbuf;
@ -913,9 +914,9 @@ static void telnet_size(void *handle, int width, int height)
/*
* Send Telnet special codes.
*/
static void telnet_special(void *handle, Telnet_Special code)
static void telnet_special(Backend *be, Telnet_Special code)
{
Telnet telnet = (Telnet) handle;
Telnet telnet = FROMFIELD(be, struct telnet_tag, backend);
unsigned char b[2];
if (telnet->s == NULL)
@ -1008,7 +1009,7 @@ static void telnet_special(void *handle, Telnet_Special code)
}
}
static const struct telnet_special *telnet_get_specials(void *handle)
static const struct telnet_special *telnet_get_specials(Backend *be)
{
static const struct telnet_special specials[] = {
{"Are You There", TS_AYT},
@ -1031,27 +1032,27 @@ static const struct telnet_special *telnet_get_specials(void *handle)
return specials;
}
static int telnet_connected(void *handle)
static int telnet_connected(Backend *be)
{
Telnet telnet = (Telnet) handle;
Telnet telnet = FROMFIELD(be, struct telnet_tag, backend);
return telnet->s != NULL;
}
static int telnet_sendok(void *handle)
static int telnet_sendok(Backend *be)
{
/* Telnet telnet = (Telnet) handle; */
/* Telnet telnet = FROMFIELD(be, struct telnet_tag, backend); */
return 1;
}
static void telnet_unthrottle(void *handle, int backlog)
static void telnet_unthrottle(Backend *be, int backlog)
{
Telnet telnet = (Telnet) handle;
Telnet telnet = FROMFIELD(be, struct telnet_tag, backend);
sk_set_frozen(telnet->s, backlog > TELNET_MAX_BACKLOG);
}
static int telnet_ldisc(void *handle, int option)
static int telnet_ldisc(Backend *be, int option)
{
Telnet telnet = (Telnet) handle;
Telnet telnet = FROMFIELD(be, struct telnet_tag, backend);
if (option == LD_ECHO)
return telnet->echoing;
if (option == LD_EDIT)
@ -1059,20 +1060,20 @@ static int telnet_ldisc(void *handle, int option)
return FALSE;
}
static void telnet_provide_ldisc(void *handle, Ldisc *ldisc)
static void telnet_provide_ldisc(Backend *be, Ldisc *ldisc)
{
Telnet telnet = (Telnet) handle;
Telnet telnet = FROMFIELD(be, struct telnet_tag, backend);
telnet->ldisc = ldisc;
}
static void telnet_provide_logctx(void *handle, LogContext *logctx)
static void telnet_provide_logctx(Backend *be, LogContext *logctx)
{
/* This is a stub. */
}
static int telnet_exitcode(void *handle)
static int telnet_exitcode(Backend *be)
{
Telnet telnet = (Telnet) handle;
Telnet telnet = FROMFIELD(be, struct telnet_tag, backend);
if (telnet->s != NULL)
return -1; /* still connected */
else if (telnet->closed_on_socket_error)
@ -1085,12 +1086,12 @@ static int telnet_exitcode(void *handle)
/*
* cfg_info for Telnet does nothing at all.
*/
static int telnet_cfg_info(void *handle)
static int telnet_cfg_info(Backend *be)
{
return 0;
}
Backend telnet_backend = {
const struct Backend_vtable telnet_backend = {
telnet_init,
telnet_free,
telnet_reconfig,

View File

@ -1693,8 +1693,7 @@ Terminal *term_init(Conf *myconf, struct unicode_data *ucsdata,
term->lastbeep = FALSE;
term->beep_overloaded = FALSE;
term->attr_mask = 0xffffffff;
term->resize_fn = NULL;
term->resize_ctx = NULL;
term->backend = NULL;
term->in_term_out = FALSE;
term->ltemp = NULL;
term->ltemp_size = 0;
@ -1964,22 +1963,18 @@ void term_size(Terminal *term, int newrows, int newcols, int newsavelines)
update_sbar(term);
term_update(term);
if (term->resize_fn)
term->resize_fn(term->resize_ctx, term->cols, term->rows);
if (term->backend)
backend_size(term->backend, term->cols, term->rows);
}
/*
* Hand a function and context pointer to the terminal which it can
* use to notify a back end of resizes.
* Hand a backend to the terminal, so it can be notified of resizes.
*/
void term_provide_resize_fn(Terminal *term,
void (*resize_fn)(void *, int, int),
void *resize_ctx)
void term_provide_backend(Terminal *term, Backend *backend)
{
term->resize_fn = resize_fn;
term->resize_ctx = resize_ctx;
if (resize_fn && term->cols > 0 && term->rows > 0)
resize_fn(resize_ctx, term->cols, term->rows);
term->backend = backend;
if (term->backend && term->cols > 0 && term->rows > 0)
backend_size(term->backend, term->cols, term->rows);
}
/* Find the bottom line on the screen that has any content.

View File

@ -227,8 +227,7 @@ struct terminal_tag {
wchar_t *paste_buffer;
int paste_len, paste_pos;
void (*resize_fn)(void *, int, int);
void *resize_ctx;
Backend *backend;
Ldisc *ldisc;

View File

@ -32,36 +32,36 @@
#include "putty.h"
static const char *null_init(void *, void **, Conf *, const char *, int,
static const char *null_init(void *, Backend **, Conf *, const char *, int,
char **, int, int);
static const char *loop_init(void *, void **, Conf *, const char *, int,
static const char *loop_init(void *, Backend **, Conf *, const char *, int,
char **, int, int);
static void null_free(void *);
static void loop_free(void *);
static void null_reconfig(void *, Conf *);
static int null_send(void *, const char *, int);
static int loop_send(void *, const char *, int);
static int null_sendbuffer(void *);
static void null_size(void *, int, int);
static void null_special(void *, Telnet_Special);
static const struct telnet_special *null_get_specials(void *handle);
static int null_connected(void *);
static int null_exitcode(void *);
static int null_sendok(void *);
static int null_ldisc(void *, int);
static void null_provide_ldisc(void *, Ldisc *);
static void null_provide_logctx(void *, LogContext *);
static void null_unthrottle(void *, int);
static int null_cfg_info(void *);
static void null_free(Backend *);
static void loop_free(Backend *);
static void null_reconfig(Backend *, Conf *);
static int null_send(Backend *, const char *, int);
static int loop_send(Backend *, const char *, int);
static int null_sendbuffer(Backend *);
static void null_size(Backend *, int, int);
static void null_special(Backend *, Telnet_Special);
static const struct telnet_special *null_get_specials(Backend *);
static int null_connected(Backend *);
static int null_exitcode(Backend *);
static int null_sendok(Backend *);
static int null_ldisc(Backend *, int);
static void null_provide_ldisc(Backend *, Ldisc *);
static void null_provide_logctx(Backend *, LogContext *);
static void null_unthrottle(Backend *, int);
static int null_cfg_info(Backend *);
Backend null_backend = {
const struct Backend_vtable null_backend = {
null_init, null_free, null_reconfig, null_send, null_sendbuffer, null_size,
null_special, null_get_specials, null_connected, null_exitcode, null_sendok,
null_ldisc, null_provide_ldisc, null_provide_logctx, null_unthrottle,
null_cfg_info, NULL /* test_for_upstream */, "null", -1, 0
};
Backend loop_backend = {
const struct Backend_vtable loop_backend = {
loop_init, loop_free, null_reconfig, loop_send, null_sendbuffer, null_size,
null_special, null_get_specials, null_connected, null_exitcode, null_sendok,
null_ldisc, null_provide_ldisc, null_provide_logctx, null_unthrottle,
@ -70,102 +70,104 @@ Backend loop_backend = {
struct loop_state {
Terminal *term;
Backend backend;
};
static const char *null_init(void *frontend_handle, void **backend_handle,
static const char *null_init(void *frontend_handle, Backend **backend_handle,
Conf *conf, const char *host, int port,
char **realhost, int nodelay, int keepalive) {
*backend_handle = NULL;
return NULL;
}
static const char *loop_init(void *frontend_handle, void **backend_handle,
static const char *loop_init(void *frontend_handle, Backend **backend_handle,
Conf *conf, const char *host, int port,
char **realhost, int nodelay, int keepalive) {
struct loop_state *st = snew(struct loop_state);
st->term = frontend_handle;
*backend_handle = st;
*backend_handle = &st->backend;
return NULL;
}
static void null_free(void *handle)
static void null_free(Backend *be)
{
}
static void loop_free(void *handle)
static void loop_free(Backend *be)
{
struct loop_state *st = FROMFIELD(be, struct loop_state, backend);
sfree(handle);
sfree(st);
}
static void null_reconfig(void *handle, Conf *conf) {
static void null_reconfig(Backend *be, Conf *conf) {
}
static int null_send(void *handle, const char *buf, int len) {
static int null_send(Backend *be, const char *buf, int len) {
return 0;
}
static int loop_send(void *handle, const char *buf, int len) {
struct loop_state *st = handle;
static int loop_send(Backend *be, const char *buf, int len) {
struct loop_state *st = FROMFIELD(be, struct loop_state, backend);
return from_backend(st->term, 0, buf, len);
}
static int null_sendbuffer(void *handle) {
static int null_sendbuffer(Backend *be) {
return 0;
}
static void null_size(void *handle, int width, int height) {
static void null_size(Backend *be, int width, int height) {
}
static void null_special(void *handle, Telnet_Special code) {
static void null_special(Backend *be, Telnet_Special code) {
}
static const struct telnet_special *null_get_specials (void *handle) {
static const struct telnet_special *null_get_specials (Backend *be) {
return NULL;
}
static int null_connected(void *handle) {
static int null_connected(Backend *be) {
return 0;
}
static int null_exitcode(void *handle) {
static int null_exitcode(Backend *be) {
return 0;
}
static int null_sendok(void *handle) {
static int null_sendok(Backend *be) {
return 1;
}
static void null_unthrottle(void *handle, int backlog) {
static void null_unthrottle(Backend *be, int backlog) {
}
static int null_ldisc(void *handle, int option) {
static int null_ldisc(Backend *be, int option) {
return 0;
}
static void null_provide_ldisc (void *handle, Ldisc *ldisc) {
static void null_provide_ldisc (Backend *be, Ldisc *ldisc) {
}
static void null_provide_logctx(void *handle, LogContext *logctx) {
static void null_provide_logctx(Backend *be, LogContext *logctx) {
}
static int null_cfg_info(void *handle)
static int null_cfg_info(Backend *be)
{
return 0;
}

View File

@ -159,8 +159,7 @@ struct gui_data {
char *icontitle;
int master_fd, master_func_id;
Ldisc *ldisc;
Backend *back;
void *backhandle;
Backend *backend;
Terminal *term;
LogContext *logctx;
int exited;
@ -1609,8 +1608,8 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
#ifdef KEY_EVENT_DIAGNOSTICS
debug((" - Ctrl-Break special case, sending TS_BRK\n"));
#endif
if (inst->back)
inst->back->special(inst->backhandle, TS_BRK);
if (inst->backend)
backend_special(inst->backend, TS_BRK);
return TRUE;
}
@ -2399,7 +2398,7 @@ static void exit_callback(void *vinst)
int exitcode, close_on_exit;
if (!inst->exited &&
(exitcode = inst->back->exitcode(inst->backhandle)) >= 0) {
(exitcode = backend_exitcode(inst->backend)) >= 0) {
destroy_inst_connection(inst);
close_on_exit = conf_get_int(inst->conf, CONF_close_on_exit);
@ -2424,13 +2423,12 @@ static void destroy_inst_connection(struct gui_data *inst)
ldisc_free(inst->ldisc);
inst->ldisc = NULL;
}
if (inst->backhandle) {
inst->back->free(inst->backhandle);
inst->backhandle = NULL;
inst->back = NULL;
if (inst->backend) {
backend_free(inst->backend);
inst->backend = NULL;
}
if (inst->term)
term_provide_resize_fn(inst->term, NULL, NULL);
term_provide_backend(inst->term, NULL);
if (inst->menu) {
update_specials_menu(inst);
gtk_widget_set_sensitive(inst->restartitem, TRUE);
@ -4480,8 +4478,8 @@ void special_menuitem(GtkMenuItem *item, gpointer data)
int code = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(item),
"user-data"));
if (inst->back)
inst->back->special(inst->backhandle, code);
if (inst->backend)
backend_special(inst->backend, code);
}
void about_menuitem(GtkMenuItem *item, gpointer data)
@ -4582,7 +4580,7 @@ void change_settings_menuitem(GtkMenuItem *item, gpointer data)
dialog = create_config_box(
title, ctx->newconf, 1,
inst->back ? inst->back->cfg_info(inst->backhandle) : 0,
inst->backend ? backend_cfg_info(inst->backend) : 0,
after_change_settings_dialog, ctx);
register_dialog(inst, DIALOG_SLOT_RECONFIGURE, dialog);
@ -4633,8 +4631,8 @@ static void after_change_settings_dialog(void *vctx, int retval)
term_reconfig(inst->term, inst->conf);
setup_clipboards(inst, inst->term, inst->conf);
/* Pass new config data to the back end */
if (inst->back)
inst->back->reconfig(inst->backhandle, inst->conf);
if (inst->backend)
backend_reconfig(inst->backend, inst->conf);
cache_conf_values(inst);
@ -4851,7 +4849,7 @@ void restart_session_menuitem(GtkMenuItem *item, gpointer data)
{
struct gui_data *inst = (struct gui_data *)data;
if (!inst->back) {
if (!inst->backend) {
logevent(inst, "----- Session restarted -----");
term_pwron(inst->term, FALSE);
start_backend(inst);
@ -4984,8 +4982,8 @@ void update_specials_menu(void *frontend)
const struct telnet_special *specials;
if (inst->back)
specials = inst->back->get_specials(inst->backhandle);
if (inst->backend)
specials = backend_get_specials(inst->backend);
else
specials = NULL;
@ -5045,20 +5043,20 @@ void update_specials_menu(void *frontend)
static void start_backend(struct gui_data *inst)
{
extern Backend *select_backend(Conf *conf);
const struct Backend_vtable *vt;
char *realhost;
const char *error;
char *s;
inst->back = select_backend(inst->conf);
vt = select_backend(inst->conf);
error = inst->back->init((void *)inst, &inst->backhandle,
inst->conf,
conf_get_str(inst->conf, CONF_host),
conf_get_int(inst->conf, CONF_port),
&realhost,
conf_get_int(inst->conf, CONF_tcp_nodelay),
conf_get_int(inst->conf, CONF_tcp_keepalives));
error = backend_init(vt, (void *)inst, &inst->backend,
inst->conf,
conf_get_str(inst->conf, CONF_host),
conf_get_int(inst->conf, CONF_port),
&realhost,
conf_get_int(inst->conf, CONF_tcp_nodelay),
conf_get_int(inst->conf, CONF_tcp_keepalives));
if (error) {
char *msg = dupprintf("Unable to open connection to %s:\n%s",
@ -5079,13 +5077,11 @@ static void start_backend(struct gui_data *inst)
}
sfree(realhost);
inst->back->provide_logctx(inst->backhandle, inst->logctx);
backend_provide_logctx(inst->backend, inst->logctx);
term_provide_resize_fn(inst->term, inst->back->size, inst->backhandle);
term_provide_backend(inst->term, inst->backend);
inst->ldisc =
ldisc_create(inst->conf, inst->term, inst->back, inst->backhandle,
inst);
inst->ldisc = ldisc_create(inst->conf, inst->term, inst->backend, inst);
gtk_widget_set_sensitive(inst->restartitem, FALSE);
}

View File

@ -67,7 +67,7 @@ struct FontSpec *fontspec_new(const char *name);
typedef void *Context; /* FIXME: probably needs changing */
extern Backend pty_backend;
extern const struct Backend_vtable pty_backend;
#define BROKEN_PIPE_ERROR_CODE EPIPE /* used in sshshare.c */
@ -178,6 +178,8 @@ void window_setup_error(const char *errmsg);
GtkWidget *make_gtk_toplevel_window(void *frontend);
#endif
const struct Backend_vtable *select_backend(Conf *conf);
/* Defined in gtkcomm.c */
void gtkcomm_setup(void);
@ -324,9 +326,9 @@ void *sk_getxdmdata(Socket sock, int *lenp);
} while (0)
/*
* Exports from winser.c.
* Exports from uxser.c.
*/
extern Backend serial_backend;
extern const struct Backend_vtable serial_backend;
/*
* uxpeer.c, wrapping getsockopt(SO_PEERCRED).

View File

@ -91,8 +91,7 @@ void cmdline_error(const char *p, ...)
static int local_tty = FALSE; /* do we have a local tty? */
static Backend *back;
static void *backhandle;
static Backend *backend;
static Conf *conf;
/*
@ -459,13 +458,13 @@ static void from_tty(void *vbuf, unsigned len)
} else {
q = memchr(p, '\xff', end - p);
if (q == NULL) q = end;
back->send(backhandle, p, q - p);
backend_send(backend, p, q - p);
p = q;
}
break;
case FF:
if (*p == '\xff') {
back->send(backhandle, p, 1);
backend_send(backend, p, 1);
p++;
state = NORMAL;
} else if (*p == '\0') {
@ -475,7 +474,7 @@ static void from_tty(void *vbuf, unsigned len)
break;
case FF00:
if (*p == '\0') {
back->special(backhandle, TS_BRK);
backend_special(backend, TS_BRK);
} else {
/*
* Pretend that PARMRK wasn't set. This involves
@ -494,11 +493,11 @@ static void from_tty(void *vbuf, unsigned len)
if (!(orig_termios.c_iflag & IGNPAR)) {
/* PE/FE get passed on as NUL. */
*p = 0;
back->send(backhandle, p, 1);
backend_send(backend, p, 1);
}
} else {
/* INPCK not set. Assume we got a parity error. */
back->send(backhandle, p, 1);
backend_send(backend, p, 1);
}
}
p++;
@ -606,6 +605,7 @@ int main(int argc, char **argv)
int just_test_share_exists = FALSE;
unsigned long now;
struct winsize size;
const struct Backend_vtable *backvt;
fdlist = NULL;
fdcount = fdsize = 0;
@ -643,10 +643,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);
}
@ -766,8 +766,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) {
backvt = backend_vt_from_proto(conf_get_int(conf, CONF_protocol));
if (!backvt) {
fprintf(stderr,
"Internal fault: Unsupported protocol found\n");
return 1;
@ -817,13 +817,13 @@ int main(int argc, char **argv)
conf_set_int(conf, CONF_ssh_simple, TRUE);
if (just_test_share_exists) {
if (!back->test_for_upstream) {
if (!backvt->test_for_upstream) {
fprintf(stderr, "Connection sharing not supported for connection "
"type '%s'\n", back->name);
"type '%s'\n", backvt->name);
return 1;
}
if (back->test_for_upstream(conf_get_str(conf, CONF_host),
conf_get_int(conf, CONF_port), conf))
if (backvt->test_for_upstream(conf_get_str(conf, CONF_host),
conf_get_int(conf, CONF_port), conf))
return 0;
else
return 1;
@ -845,17 +845,17 @@ int main(int argc, char **argv)
__AFL_INIT();
#endif
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(backvt, 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\n", error);
return 1;
}
back->provide_logctx(backhandle, logctx);
ldisc_create(conf, NULL, back, backhandle, NULL);
backend_provide_logctx(backend, logctx);
ldisc_create(conf, NULL, backend, NULL);
sfree(realhost);
}
@ -885,9 +885,9 @@ int main(int argc, char **argv)
FD_SET_MAX(signalpipe[0], maxfd, rset);
if (!sending &&
back->connected(backhandle) &&
back->sendok(backhandle) &&
back->sendbuffer(backhandle) < MAX_STDIN_BACKLOG) {
backend_connected(backend) &&
backend_sendok(backend) &&
backend_sendbuffer(backend) < MAX_STDIN_BACKLOG) {
/* If we're OK to send, then try to read from stdin. */
FD_SET_MAX(STDIN_FILENO, maxfd, rset);
}
@ -988,46 +988,46 @@ int main(int argc, char **argv)
/* ignore error */;
/* ignore its value; it'll be `x' */
if (ioctl(STDIN_FILENO, TIOCGWINSZ, (void *)&size) >= 0)
back->size(backhandle, size.ws_col, size.ws_row);
backend_size(backend, size.ws_col, size.ws_row);
}
if (FD_ISSET(STDIN_FILENO, &rset)) {
char buf[4096];
int ret;
if (back->connected(backhandle)) {
if (backend_connected(backend)) {
ret = read(STDIN_FILENO, buf, sizeof(buf));
if (ret < 0) {
perror("stdin: read");
exit(1);
} else if (ret == 0) {
back->special(backhandle, TS_EOF);
backend_special(backend, TS_EOF);
sending = FALSE; /* send nothing further after this */
} else {
if (local_tty)
from_tty(buf, ret);
else
back->send(backhandle, buf, ret);
backend_send(backend, buf, ret);
}
}
}
if (FD_ISSET(STDOUT_FILENO, &wset)) {
back->unthrottle(backhandle, try_output(FALSE));
backend_unthrottle(backend, try_output(FALSE));
}
if (FD_ISSET(STDERR_FILENO, &wset)) {
back->unthrottle(backhandle, try_output(TRUE));
backend_unthrottle(backend, try_output(TRUE));
}
run_toplevel_callbacks();
if (!back->connected(backhandle) &&
if (!backend_connected(backend) &&
bufchain_size(&stdout_data) == 0 &&
bufchain_size(&stderr_data) == 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

@ -13,7 +13,7 @@ const int new_session = 0, saved_sessions = 0; /* or these */
const int dup_check_launchable = 0; /* no need to check host name in conf */
const int use_pty_argv = TRUE;
Backend *select_backend(Conf *conf)
const struct Backend_vtable *select_backend(Conf *conf)
{
return &pty_backend;
}

View File

@ -78,6 +78,7 @@ struct pty_tag {
int child_dead, finished;
int exit_code;
bufchain output_data;
Backend backend;
};
/*
@ -728,9 +729,9 @@ static void pty_uxsel_setup(Pty pty)
* Also places the canonical host name into `realhost'. It must be
* freed by the caller.
*/
static const char *pty_init(void *frontend, void **backend_handle, Conf *conf,
const char *host, int port, char **realhost,
int nodelay, int keepalive)
static const char *pty_init(void *frontend, Backend **backend_handle,
Conf *conf, const char *host, int port,
char **realhost, int nodelay, int keepalive)
{
int slavefd;
pid_t pid, pgrp;
@ -752,7 +753,8 @@ static const char *pty_init(void *frontend, void **backend_handle, Conf *conf,
}
pty->frontend = frontend;
*backend_handle = NULL; /* we can't sensibly use this, sadly */
pty->backend.vt = &pty_backend;
*backend_handle = &pty->backend;
pty->conf = conf_copy(conf);
pty->term_width = conf_get_int(conf, CONF_width);
@ -1025,16 +1027,14 @@ static const char *pty_init(void *frontend, void **backend_handle, Conf *conf,
}
pty_uxsel_setup(pty);
*backend_handle = pty;
*realhost = dupstr("");
return NULL;
}
static void pty_reconfig(void *handle, Conf *conf)
static void pty_reconfig(Backend *be, Conf *conf)
{
Pty pty = (Pty)handle;
Pty pty = FROMFIELD(be, struct pty_tag, backend);
/*
* We don't have much need to reconfigure this backend, but
* unfortunately we do need to pick up the setting of Close On
@ -1046,9 +1046,9 @@ static void pty_reconfig(void *handle, Conf *conf)
/*
* Stub routine (never called in pterm).
*/
static void pty_free(void *handle)
static void pty_free(Backend *be)
{
Pty pty = (Pty)handle;
Pty pty = FROMFIELD(be, struct pty_tag, backend);
/* Either of these may fail `not found'. That's fine with us. */
del234(ptys_by_pid, pty);
@ -1099,9 +1099,9 @@ static void pty_try_write(Pty pty)
/*
* Called to send data down the pty.
*/
static int pty_send(void *handle, const char *buf, int len)
static int pty_send(Backend *be, const char *buf, int len)
{
Pty pty = (Pty)handle;
Pty pty = FROMFIELD(be, struct pty_tag, backend);
if (pty->master_fd < 0)
return 0; /* ignore all writes if fd closed */
@ -1129,18 +1129,18 @@ static void pty_close(Pty pty)
/*
* Called to query the current socket sendability status.
*/
static int pty_sendbuffer(void *handle)
static int pty_sendbuffer(Backend *be)
{
/* Pty pty = (Pty)handle; */
/* Pty pty = FROMFIELD(be, struct pty_tag, backend); */
return 0;
}
/*
* Called to set the size of the window
*/
static void pty_size(void *handle, int width, int height)
static void pty_size(Backend *be, int width, int height)
{
Pty pty = (Pty)handle;
Pty pty = FROMFIELD(be, struct pty_tag, backend);
struct winsize size;
pty->term_width = width;
@ -1159,9 +1159,9 @@ static void pty_size(void *handle, int width, int height)
/*
* Send special codes.
*/
static void pty_special(void *handle, Telnet_Special code)
static void pty_special(Backend *be, Telnet_Special code)
{
/* Pty pty = (Pty)handle; */
/* Pty pty = FROMFIELD(be, struct pty_tag, backend); */
/* Do nothing! */
return;
}
@ -1170,9 +1170,9 @@ static void pty_special(void *handle, Telnet_Special code)
* Return a list of the special codes that make sense in this
* protocol.
*/
static const struct telnet_special *pty_get_specials(void *handle)
static const struct telnet_special *pty_get_specials(Backend *be)
{
/* Pty pty = (Pty)handle; */
/* Pty pty = FROMFIELD(be, struct pty_tag, backend); */
/*
* Hmm. When I get round to having this actually usable, it
* might be quite nice to have the ability to deliver a few
@ -1182,58 +1182,58 @@ static const struct telnet_special *pty_get_specials(void *handle)
return NULL;
}
static int pty_connected(void *handle)
static int pty_connected(Backend *be)
{
/* Pty pty = (Pty)handle; */
/* Pty pty = FROMFIELD(be, struct pty_tag, backend); */
return TRUE;
}
static int pty_sendok(void *handle)
static int pty_sendok(Backend *be)
{
/* Pty pty = (Pty)handle; */
/* Pty pty = FROMFIELD(be, struct pty_tag, backend); */
return 1;
}
static void pty_unthrottle(void *handle, int backlog)
static void pty_unthrottle(Backend *be, int backlog)
{
/* Pty pty = (Pty)handle; */
/* Pty pty = FROMFIELD(be, struct pty_tag, backend); */
/* do nothing */
}
static int pty_ldisc(void *handle, int option)
static int pty_ldisc(Backend *be, int option)
{
/* Pty pty = (Pty)handle; */
/* Pty pty = FROMFIELD(be, struct pty_tag, backend); */
return 0; /* neither editing nor echoing */
}
static void pty_provide_ldisc(void *handle, Ldisc *ldisc)
static void pty_provide_ldisc(Backend *be, Ldisc *ldisc)
{
/* Pty pty = (Pty)handle; */
/* Pty pty = FROMFIELD(be, struct pty_tag, backend); */
/* This is a stub. */
}
static void pty_provide_logctx(void *handle, LogContext *logctx)
static void pty_provide_logctx(Backend *be, LogContext *logctx)
{
/* Pty pty = (Pty)handle; */
/* Pty pty = FROMFIELD(be, struct pty_tag, backend); */
/* This is a stub. */
}
static int pty_exitcode(void *handle)
static int pty_exitcode(Backend *be)
{
Pty pty = (Pty)handle;
Pty pty = FROMFIELD(be, struct pty_tag, backend);
if (!pty->finished)
return -1; /* not dead yet */
else
return pty->exit_code;
}
static int pty_cfg_info(void *handle)
static int pty_cfg_info(Backend *be)
{
/* Pty pty = (Pty)handle; */
/* Pty pty = FROMFIELD(be, struct pty_tag, backend); */
return 0;
}
Backend pty_backend = {
const struct Backend_vtable pty_backend = {
pty_init,
pty_free,
pty_reconfig,

View File

@ -37,11 +37,12 @@ void cleanup_exit(int code)
exit(code);
}
Backend *select_backend(Conf *conf)
const struct Backend_vtable *select_backend(Conf *conf)
{
Backend *back = backend_from_proto(conf_get_int(conf, CONF_protocol));
assert(back != NULL);
return back;
const struct Backend_vtable *vt =
backend_vt_from_proto(conf_get_int(conf, CONF_protocol));
assert(vt != NULL);
return vt;
}
void initial_config_box(Conf *conf, post_dialog_fn_t after, void *afterctx)
@ -83,9 +84,10 @@ void setup(int single)
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;
}
}

View File

@ -23,6 +23,7 @@ typedef struct serial_backend_data {
int finished;
int inbufsize;
bufchain output_data;
Backend backend;
} *Serial;
/*
@ -287,7 +288,7 @@ static const char *serial_configure(Serial serial, 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)
@ -297,7 +298,8 @@ static const char *serial_init(void *frontend_handle, void **backend_handle,
char *line;
serial = snew(struct serial_backend_data);
*backend_handle = serial;
serial->backend.vt = &serial_backend;
*backend_handle = &serial->backend;
serial->frontend = frontend_handle;
serial->finished = FALSE;
@ -345,9 +347,9 @@ static void serial_close(Serial serial)
}
}
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_close(serial);
@ -356,9 +358,9 @@ static void serial_free(void *handle)
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);
/*
* FIXME: what should we do if this returns an error?
@ -460,9 +462,9 @@ static void serial_try_write(Serial serial)
/*
* 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->fd < 0)
return 0;
@ -476,16 +478,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 bufchain_size(&serial->output_data);
}
/*
* 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;
@ -494,9 +496,9 @@ static void serial_size(void *handle, int width, int height)
/*
* 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->fd >= 0 && code == TS_BRK) {
tcsendbreak(serial->fd, 0);
@ -510,7 +512,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},
@ -519,24 +521,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);
serial->inbufsize = backlog;
serial_uxsel_setup(serial);
}
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.
@ -544,19 +546,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->fd >= 0)
return -1; /* still connected */
else
@ -567,12 +569,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

@ -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.