diff --git a/be_all.c b/be_all.c index c58903cc..6a09f748 100644 --- a/be_all.c +++ b/be_all.c @@ -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, diff --git a/be_all_s.c b/be_all_s.c index 0ffd0737..d40d7639 100644 --- a/be_all_s.c +++ b/be_all_s.c @@ -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, diff --git a/be_none.c b/be_none.c index 688b8daf..7cf52fa1 100644 --- a/be_none.c +++ b/be_none.c @@ -6,6 +6,6 @@ #include #include "putty.h" -Backend *backends[] = { +const struct Backend_vtable *const backends[] = { NULL }; diff --git a/be_nos_s.c b/be_nos_s.c index a574ead9..a12125ab 100644 --- a/be_nos_s.c +++ b/be_nos_s.c @@ -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, diff --git a/be_nossh.c b/be_nossh.c index 33d783a8..463497a2 100644 --- a/be_nossh.c +++ b/be_nossh.c @@ -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, diff --git a/be_ssh.c b/be_ssh.c index 57d241c2..ec1da386 100644 --- a/be_ssh.c +++ b/be_ssh.c @@ -10,7 +10,7 @@ const int be_default_protocol = PROT_SSH; -Backend *backends[] = { +const struct Backend_vtable *const backends[] = { &ssh_backend, NULL }; diff --git a/cmdline.c b/cmdline.c index 0fefb428..0ce3f8a1 100644 --- a/cmdline.c +++ b/cmdline.c @@ -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); diff --git a/config.c b/config.c index 16d3f7d5..fac7dc3d 100644 --- a/config.c +++ b/config.c @@ -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. diff --git a/defs.h b/defs.h index 58a4edff..43f56dfe 100644 --- a/defs.h +++ b/defs.h @@ -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 diff --git a/ldisc.c b/ldisc.c index ba90e1d0..3596ea63 100644 --- a/ldisc.c +++ b/ldisc.c @@ -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); } } } diff --git a/ldisc.h b/ldisc.h index 44f5772f..af7afde3 100644 --- a/ldisc.h +++ b/ldisc.h @@ -10,8 +10,7 @@ struct Ldisc_tag { Terminal *term; - Backend *back; - void *backhandle; + Backend *backend; void *frontend; /* diff --git a/pinger.c b/pinger.c index d8f110ac..c83b71d2 100644 --- a/pinger.c +++ b/pinger.c @@ -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; diff --git a/pscp.c b/pscp.c index bc2140f5..854e6815 100644 --- a/pscp.c +++ b/pscp.c @@ -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); } diff --git a/psftp.c b/psftp.c index cd419ebe..c2d23832 100644 --- a/psftp.c +++ b/psftp.c @@ -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); } diff --git a/putty.h b/putty.h index 14451756..2f53d645 100644 --- a/putty.h +++ b/putty.h @@ -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); diff --git a/raw.c b/raw.c index 658bd030..56eb0385 100644 --- a/raw.c +++ b/raw.c @@ -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, diff --git a/rlogin.c b/rlogin.c index dcba9c0c..978e3084 100644 --- a/rlogin.c +++ b/rlogin.c @@ -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, diff --git a/settings.c b/settings.c index d7e65e2d..ecdb3a4b 100644 --- a/settings.c +++ b/settings.c @@ -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); } } diff --git a/ssh.c b/ssh.c index 1b75fb84..952b901f 100644 --- a/ssh.c +++ b/ssh.c @@ -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, diff --git a/ssh.h b/ssh.h index 6c606abb..4529bbcc 100644 --- a/ssh.h +++ b/ssh.h @@ -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); diff --git a/telnet.c b/telnet.c index ed585276..673c152f 100644 --- a/telnet.c +++ b/telnet.c @@ -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, diff --git a/terminal.c b/terminal.c index 04e222d0..1dc83dc1 100644 --- a/terminal.c +++ b/terminal.c @@ -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. diff --git a/terminal.h b/terminal.h index 244ff3bc..8ec256d4 100644 --- a/terminal.h +++ b/terminal.h @@ -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; diff --git a/testback.c b/testback.c index 78b89333..f3e9e35f 100644 --- a/testback.c +++ b/testback.c @@ -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; } diff --git a/unix/gtkwin.c b/unix/gtkwin.c index 18bea32f..6867ac07 100644 --- a/unix/gtkwin.c +++ b/unix/gtkwin.c @@ -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); } diff --git a/unix/unix.h b/unix/unix.h index 14ce470a..f9ff3c68 100644 --- a/unix/unix.h +++ b/unix/unix.h @@ -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). diff --git a/unix/uxplink.c b/unix/uxplink.c index 64e29c31..7bcac362 100644 --- a/unix/uxplink.c +++ b/unix/uxplink.c @@ -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 */ diff --git a/unix/uxpterm.c b/unix/uxpterm.c index d80c3780..4df8b164 100644 --- a/unix/uxpterm.c +++ b/unix/uxpterm.c @@ -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; } diff --git a/unix/uxpty.c b/unix/uxpty.c index b1204a10..870e5156 100644 --- a/unix/uxpty.c +++ b/unix/uxpty.c @@ -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, diff --git a/unix/uxputty.c b/unix/uxputty.c index fb280187..52e4cef1 100644 --- a/unix/uxputty.c +++ b/unix/uxputty.c @@ -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; } } diff --git a/unix/uxser.c b/unix/uxser.c index 50eb83e6..e352f049 100644 --- a/unix/uxser.c +++ b/unix/uxser.c @@ -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, diff --git a/windows/wincfg.c b/windows/wincfg.c index 950cef11..9e242875 100644 --- a/windows/wincfg.c +++ b/windows/wincfg.c @@ -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", diff --git a/windows/window.c b/windows/window.c index 80b94201..0d29b136 100644 --- a/windows/window.c +++ b/windows/window.c @@ -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 */ diff --git a/windows/winplink.c b/windows/winplink.c index a940677f..455b18a7 100644 --- a/windows/winplink.c +++ b/windows/winplink.c @@ -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 */ diff --git a/windows/winser.c b/windows/winser.c index f0ea94bd..1efac931 100644 --- a/windows/winser.c +++ b/windows/winser.c @@ -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, diff --git a/windows/winstuff.h b/windows/winstuff.h index 727c4b06..87dc48b6 100644 --- a/windows/winstuff.h +++ b/windows/winstuff.h @@ -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.