mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00:00
Introduce a new 'Interactor' trait.
This trait will be implemented by anything that wants to display interactive prompts or notifications to the user in the course of setting up a network connection, _or_ anything that wants to make a network connection whose proxy setup might in turn need to do that. To begin with, that means every Backend that makes network connections at all must be an Interactor, because any of those network connections might be proxied via an SSH jump host which might need to interact with the user. I'll fill in the contents of this trait over the next few commits, to keep the patches comprehensible. For the moment, I've just introduced the trait, set up implementations of it in the five network backends, and given it a single 'description' method. The previous 'description' methods of Backend and Plug are now removed, and their work is done by the new Interactor method instead. (I changed my mind since last week about where that should best live.) This isn't too much of an upheaval, fortunately, because I hadn't got round yet to committing anything that used those methods!
This commit is contained in:
parent
74a0be9c56
commit
44db74ec51
2
defs.h
2
defs.h
@ -101,6 +101,8 @@ typedef struct SocketPeerInfo SocketPeerInfo;
|
||||
|
||||
typedef struct Backend Backend;
|
||||
typedef struct BackendVtable BackendVtable;
|
||||
typedef struct Interactor Interactor;
|
||||
typedef struct InteractorVtable InteractorVtable;
|
||||
|
||||
typedef struct Ldisc_tag Ldisc;
|
||||
typedef struct LogContext LogContext;
|
||||
|
22
network.h
22
network.h
@ -129,26 +129,6 @@ struct PlugVtable {
|
||||
* want the connection for some reason, or 0 on success.
|
||||
*/
|
||||
int (*accepting)(Plug *p, accept_fn_t constructor, accept_ctx_t ctx);
|
||||
|
||||
/*
|
||||
* Returns a user-facing description of the nature of the network
|
||||
* connection being made. Used in interactive proxy authentication
|
||||
* to announce which connection attempt is now in control of the
|
||||
* Seat.
|
||||
*
|
||||
* The idea is not just to be written in natural language, but to
|
||||
* connect with the user's idea of _why_ they think some
|
||||
* connection is being made. For example, instead of saying 'TCP
|
||||
* connection to 123.45.67.89 port 22', you might say 'SSH
|
||||
* connection to [logical host name for SSH host key purposes]'.
|
||||
*
|
||||
* This function pointer may be NULL, or may exist but return
|
||||
* NULL, in which case no user-facing description is available.
|
||||
*
|
||||
* If a non-NULL string is returned, it must be freed by the
|
||||
* caller.
|
||||
*/
|
||||
char *(*description)(Plug *p);
|
||||
};
|
||||
|
||||
/* Proxy indirection layer.
|
||||
@ -256,8 +236,6 @@ static inline void plug_sent (Plug *p, size_t bufsize)
|
||||
{ p->vt->sent(p, bufsize); }
|
||||
static inline int plug_accepting(Plug *p, accept_fn_t cons, accept_ctx_t ctx)
|
||||
{ return p->vt->accepting(p, cons, ctx); }
|
||||
static inline char *plug_description(Plug *p)
|
||||
{ return p->vt->description ? p->vt->description(p) : NULL; }
|
||||
|
||||
/*
|
||||
* Special error values are returned from sk_namelookup and sk_new
|
||||
|
@ -25,6 +25,7 @@ struct Raw {
|
||||
|
||||
Plug plug;
|
||||
Backend backend;
|
||||
Interactor interactor;
|
||||
};
|
||||
|
||||
static void raw_size(Backend *be, int width, int height);
|
||||
@ -116,24 +117,21 @@ static void raw_sent(Plug *plug, size_t bufsize)
|
||||
seat_sent(raw->seat, raw->bufsize);
|
||||
}
|
||||
|
||||
static char *raw_plug_description(Plug *plug)
|
||||
{
|
||||
Raw *raw = container_of(plug, Raw, plug);
|
||||
return dupstr(raw->description);
|
||||
}
|
||||
|
||||
static char *raw_backend_description(Backend *backend)
|
||||
{
|
||||
Raw *raw = container_of(backend, Raw, backend);
|
||||
return dupstr(raw->description);
|
||||
}
|
||||
|
||||
static const PlugVtable Raw_plugvt = {
|
||||
.log = raw_log,
|
||||
.closing = raw_closing,
|
||||
.receive = raw_receive,
|
||||
.sent = raw_sent,
|
||||
.description = raw_plug_description,
|
||||
};
|
||||
|
||||
static char *raw_description(Interactor *itr)
|
||||
{
|
||||
Raw *raw = container_of(itr, Raw, interactor);
|
||||
return dupstr(raw->description);
|
||||
}
|
||||
|
||||
static const InteractorVtable Raw_interactorvt = {
|
||||
.description = raw_description,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -159,6 +157,8 @@ static char *raw_init(const BackendVtable *vt, Seat *seat,
|
||||
memset(raw, 0, sizeof(Raw));
|
||||
raw->plug.vt = &Raw_plugvt;
|
||||
raw->backend.vt = vt;
|
||||
raw->interactor.vt = &Raw_interactorvt;
|
||||
raw->backend.interactor = &raw->interactor;
|
||||
raw->s = NULL;
|
||||
raw->closed_on_socket_error = false;
|
||||
*backend_handle = &raw->backend;
|
||||
@ -354,7 +354,6 @@ const BackendVtable raw_backend = {
|
||||
.provide_ldisc = raw_provide_ldisc,
|
||||
.unthrottle = raw_unthrottle,
|
||||
.cfg_info = raw_cfg_info,
|
||||
.description = raw_backend_description,
|
||||
.id = "raw",
|
||||
.displayname_tc = "Raw",
|
||||
.displayname_lc = "raw",
|
||||
|
@ -32,6 +32,7 @@ struct Rlogin {
|
||||
|
||||
Plug plug;
|
||||
Backend backend;
|
||||
Interactor interactor;
|
||||
};
|
||||
|
||||
static void rlogin_startup(Rlogin *rlogin, int prompt_result,
|
||||
@ -193,24 +194,21 @@ static void rlogin_startup(Rlogin *rlogin, int prompt_result,
|
||||
ldisc_check_sendok(rlogin->ldisc);
|
||||
}
|
||||
|
||||
static char *rlogin_plug_description(Plug *plug)
|
||||
{
|
||||
Rlogin *rlogin = container_of(plug, Rlogin, plug);
|
||||
return dupstr(rlogin->description);
|
||||
}
|
||||
|
||||
static char *rlogin_backend_description(Backend *backend)
|
||||
{
|
||||
Rlogin *rlogin = container_of(backend, Rlogin, backend);
|
||||
return dupstr(rlogin->description);
|
||||
}
|
||||
|
||||
static const PlugVtable Rlogin_plugvt = {
|
||||
.log = rlogin_log,
|
||||
.closing = rlogin_closing,
|
||||
.receive = rlogin_receive,
|
||||
.sent = rlogin_sent,
|
||||
.description = rlogin_plug_description,
|
||||
};
|
||||
|
||||
static char *rlogin_description(Interactor *itr)
|
||||
{
|
||||
Rlogin *rlogin = container_of(itr, Rlogin, interactor);
|
||||
return dupstr(rlogin->description);
|
||||
}
|
||||
|
||||
static const InteractorVtable Rlogin_interactorvt = {
|
||||
.description = rlogin_description,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -236,6 +234,8 @@ static char *rlogin_init(const BackendVtable *vt, Seat *seat,
|
||||
memset(rlogin, 0, sizeof(Rlogin));
|
||||
rlogin->plug.vt = &Rlogin_plugvt;
|
||||
rlogin->backend.vt = vt;
|
||||
rlogin->interactor.vt = &Rlogin_interactorvt;
|
||||
rlogin->backend.interactor = &rlogin->interactor;
|
||||
rlogin->s = NULL;
|
||||
rlogin->closed_on_socket_error = false;
|
||||
rlogin->seat = seat;
|
||||
@ -461,7 +461,6 @@ const BackendVtable rlogin_backend = {
|
||||
.provide_ldisc = rlogin_provide_ldisc,
|
||||
.unthrottle = rlogin_unthrottle,
|
||||
.cfg_info = rlogin_cfg_info,
|
||||
.description = rlogin_backend_description,
|
||||
.id = "rlogin",
|
||||
.displayname_tc = "Rlogin",
|
||||
.displayname_lc = "Rlogin", /* proper name, so capitalise it anyway */
|
||||
|
@ -107,6 +107,7 @@ struct supdup_tag
|
||||
|
||||
Plug plug;
|
||||
Backend backend;
|
||||
Interactor interactor;
|
||||
};
|
||||
|
||||
#define SUPDUP_MAX_BACKLOG 4096
|
||||
@ -642,17 +643,15 @@ static void supdup_send_config(Supdup *supdup)
|
||||
supdup_send_36bits(supdup, TTYROL); // scroll amount
|
||||
}
|
||||
|
||||
static char *supdup_plug_description(Plug *plug)
|
||||
static char *supdup_description(Interactor *itr)
|
||||
{
|
||||
Supdup *supdup = container_of(plug, Supdup, plug);
|
||||
Supdup *supdup = container_of(itr, Supdup, interactor);
|
||||
return dupstr(supdup->description);
|
||||
}
|
||||
|
||||
static char *supdup_backend_description(Backend *backend)
|
||||
{
|
||||
Supdup *supdup = container_of(backend, Supdup, backend);
|
||||
return dupstr(supdup->description);
|
||||
}
|
||||
static const InteractorVtable Supdup_interactorvt = {
|
||||
.description = supdup_description,
|
||||
};
|
||||
|
||||
/*
|
||||
* Called to set up the Supdup connection.
|
||||
@ -673,7 +672,6 @@ static char *supdup_init(const BackendVtable *x, Seat *seat,
|
||||
.closing = supdup_closing,
|
||||
.receive = supdup_receive,
|
||||
.sent = supdup_sent,
|
||||
.description = supdup_plug_description,
|
||||
};
|
||||
SockAddr *addr;
|
||||
const char *err;
|
||||
@ -686,6 +684,8 @@ static char *supdup_init(const BackendVtable *x, Seat *seat,
|
||||
memset(supdup, 0, sizeof(Supdup));
|
||||
supdup->plug.vt = &fn_table;
|
||||
supdup->backend.vt = &supdup_backend;
|
||||
supdup->interactor.vt = &Supdup_interactorvt;
|
||||
supdup->backend.interactor = &supdup->interactor;
|
||||
supdup->logctx = logctx;
|
||||
supdup->conf = conf_copy(conf);
|
||||
supdup->s = NULL;
|
||||
@ -952,7 +952,6 @@ const BackendVtable supdup_backend = {
|
||||
.provide_ldisc = supdup_provide_ldisc,
|
||||
.unthrottle = supdup_unthrottle,
|
||||
.cfg_info = supdup_cfg_info,
|
||||
.description = supdup_backend_description,
|
||||
.id = "supdup",
|
||||
.displayname_tc = "SUPDUP",
|
||||
.displayname_lc = "SUPDUP", /* proper name, so capitalise it anyway */
|
||||
|
@ -200,6 +200,7 @@ struct Telnet {
|
||||
|
||||
Plug plug;
|
||||
Backend backend;
|
||||
Interactor interactor;
|
||||
};
|
||||
|
||||
#define TELNET_MAX_BACKLOG 4096
|
||||
@ -681,24 +682,21 @@ static void telnet_sent(Plug *plug, size_t bufsize)
|
||||
seat_sent(telnet->seat, telnet->bufsize);
|
||||
}
|
||||
|
||||
static char *telnet_plug_description(Plug *plug)
|
||||
{
|
||||
Telnet *telnet = container_of(plug, Telnet, plug);
|
||||
return dupstr(telnet->description);
|
||||
}
|
||||
|
||||
static char *telnet_backend_description(Backend *backend)
|
||||
{
|
||||
Telnet *telnet = container_of(backend, Telnet, backend);
|
||||
return dupstr(telnet->description);
|
||||
}
|
||||
|
||||
static const PlugVtable Telnet_plugvt = {
|
||||
.log = telnet_log,
|
||||
.closing = telnet_closing,
|
||||
.receive = telnet_receive,
|
||||
.sent = telnet_sent,
|
||||
.description = telnet_plug_description,
|
||||
};
|
||||
|
||||
static char *telnet_description(Interactor *itr)
|
||||
{
|
||||
Telnet *telnet = container_of(itr, Telnet, interactor);
|
||||
return dupstr(telnet->description);
|
||||
}
|
||||
|
||||
static const InteractorVtable Telnet_interactorvt = {
|
||||
.description = telnet_description,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -724,6 +722,8 @@ static char *telnet_init(const BackendVtable *vt, Seat *seat,
|
||||
memset(telnet, 0, sizeof(Telnet));
|
||||
telnet->plug.vt = &Telnet_plugvt;
|
||||
telnet->backend.vt = vt;
|
||||
telnet->interactor.vt = &Telnet_interactorvt;
|
||||
telnet->backend.interactor = &telnet->interactor;
|
||||
telnet->conf = conf_copy(conf);
|
||||
telnet->s = NULL;
|
||||
telnet->socket_connected = false;
|
||||
@ -1098,7 +1098,6 @@ const BackendVtable telnet_backend = {
|
||||
.provide_ldisc = telnet_provide_ldisc,
|
||||
.unthrottle = telnet_unthrottle,
|
||||
.cfg_info = telnet_cfg_info,
|
||||
.description = telnet_backend_description,
|
||||
.id = "telnet",
|
||||
.displayname_tc = "Telnet",
|
||||
.displayname_lc = "Telnet", /* proper name, so capitalise it anyway */
|
||||
|
75
putty.h
75
putty.h
@ -633,8 +633,56 @@ enum {
|
||||
/* In (no)sshproxy.c */
|
||||
extern const bool ssh_proxy_supported;
|
||||
|
||||
/*
|
||||
* The Interactor trait is implemented by anything that is capable of
|
||||
* presenting interactive prompts or questions to the user during
|
||||
* network connection setup. Every Backend that ever needs to do this
|
||||
* is an Interactor, but also, while a Backend is making its initial
|
||||
* network connection, it may go via network proxy code which is also
|
||||
* an Interactor and can ask questions of its own.
|
||||
*/
|
||||
struct Interactor {
|
||||
const InteractorVtable *vt;
|
||||
};
|
||||
|
||||
struct InteractorVtable {
|
||||
/*
|
||||
* Returns a user-facing description of the nature of the network
|
||||
* connection being made. Used in interactive proxy authentication
|
||||
* to announce which connection attempt is now in control of the
|
||||
* Seat.
|
||||
*
|
||||
* The idea is not just to be written in natural language, but to
|
||||
* connect with the user's idea of _why_ they think some
|
||||
* connection is being made. For example, instead of saying 'TCP
|
||||
* connection to 123.45.67.89 port 22', you might say 'SSH
|
||||
* connection to [logical host name for SSH host key purposes]'.
|
||||
*
|
||||
* The returned string must be freed by the caller.
|
||||
*/
|
||||
char *(*description)(Interactor *itr);
|
||||
};
|
||||
|
||||
static inline char *interactor_description(Interactor *itr)
|
||||
{ return itr->vt->description(itr); }
|
||||
|
||||
/* Interactors that are Backends will find this helper function useful
|
||||
* in constructing their description strings */
|
||||
char *default_description(const BackendVtable *backvt,
|
||||
const char *host, int port);
|
||||
|
||||
/*
|
||||
* The Backend trait is the top-level one that governs each of the
|
||||
* user-facing main modes that PuTTY can use to talk to some
|
||||
* destination: SSH, Telnet, serial port, pty, etc.
|
||||
*/
|
||||
|
||||
struct Backend {
|
||||
const BackendVtable *vt;
|
||||
|
||||
/* Many Backends are also Interactors. If this one is, a pointer
|
||||
* to its Interactor trait lives here. */
|
||||
Interactor *interactor;
|
||||
};
|
||||
struct BackendVtable {
|
||||
char *(*init) (const BackendVtable *vt, Seat *seat,
|
||||
@ -680,28 +728,6 @@ struct BackendVtable {
|
||||
* connections that would be lost if this one were terminated. */
|
||||
char *(*close_warn_text)(Backend *be);
|
||||
|
||||
/*
|
||||
* Returns a user-facing description of the nature of the network
|
||||
* connection being made. Used in interactive proxy authentication
|
||||
* to announce which connection attempt is now in control of the
|
||||
* Seat.
|
||||
*
|
||||
* The idea is not just to be written in natural language, but to
|
||||
* connect with the user's idea of _why_ they think some
|
||||
* connection is being made. For example, instead of saying 'TCP
|
||||
* connection to 123.45.67.89 port 22', you might say 'SSH
|
||||
* connection to [logical host name for SSH host key purposes]'.
|
||||
*
|
||||
* This function pointer may be NULL, or may exist but return
|
||||
* NULL, in which case no user-facing description is available.
|
||||
* (Backends which are never proxied, such as pty and ConPTY, need
|
||||
* not bother to fill this in.)
|
||||
*
|
||||
* If a non-NULL string is returned, it must be freed by the
|
||||
* caller.
|
||||
*/
|
||||
char *(*description)(Backend *be);
|
||||
|
||||
/* 'id' is a machine-readable name for the backend, used in
|
||||
* saved-session storage. 'displayname_tc' and 'displayname_lc'
|
||||
* are human-readable names, one in title-case for config boxes,
|
||||
@ -750,11 +776,6 @@ static inline void backend_unthrottle(Backend *be, size_t bufsize)
|
||||
{ be->vt->unthrottle(be, bufsize); }
|
||||
static inline int backend_cfg_info(Backend *be)
|
||||
{ return be->vt->cfg_info(be); }
|
||||
static inline char *backend_description(Backend *be)
|
||||
{ return be->vt->description ? be->vt->description(be) : NULL; }
|
||||
|
||||
char *default_description(const BackendVtable *backvt,
|
||||
const char *host, int port);
|
||||
|
||||
extern const struct BackendVtable *const backends[];
|
||||
/*
|
||||
|
28
ssh/ssh.c
28
ssh/ssh.c
@ -39,6 +39,7 @@ struct Ssh {
|
||||
|
||||
Plug plug;
|
||||
Backend backend;
|
||||
Interactor interactor;
|
||||
|
||||
Ldisc *ldisc;
|
||||
LogContext *logctx;
|
||||
@ -718,24 +719,21 @@ static char *ssh_close_warn_text(Backend *be)
|
||||
return msg;
|
||||
}
|
||||
|
||||
static char *ssh_plug_description(Plug *plug)
|
||||
{
|
||||
Ssh *ssh = container_of(plug, Ssh, plug);
|
||||
return dupstr(ssh->description);
|
||||
}
|
||||
|
||||
static char *ssh_backend_description(Backend *backend)
|
||||
{
|
||||
Ssh *ssh = container_of(backend, Ssh, backend);
|
||||
return dupstr(ssh->description);
|
||||
}
|
||||
|
||||
static const PlugVtable Ssh_plugvt = {
|
||||
.log = ssh_socket_log,
|
||||
.closing = ssh_closing,
|
||||
.receive = ssh_receive,
|
||||
.sent = ssh_sent,
|
||||
.description = ssh_plug_description,
|
||||
};
|
||||
|
||||
static char *ssh_description(Interactor *itr)
|
||||
{
|
||||
Ssh *ssh = container_of(itr, Ssh, interactor);
|
||||
return dupstr(ssh->description);
|
||||
}
|
||||
|
||||
static const InteractorVtable Ssh_interactorvt = {
|
||||
.description = ssh_description,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -940,6 +938,8 @@ static char *ssh_init(const BackendVtable *vt, Seat *seat,
|
||||
ssh->term_height = conf_get_int(ssh->conf, CONF_height);
|
||||
|
||||
ssh->backend.vt = vt;
|
||||
ssh->interactor.vt = &Ssh_interactorvt;
|
||||
ssh->backend.interactor = &ssh->interactor;
|
||||
*backend_handle = &ssh->backend;
|
||||
|
||||
ssh->bare_connection = (vt->protocol == PROT_SSHCONN);
|
||||
@ -1264,7 +1264,6 @@ const BackendVtable ssh_backend = {
|
||||
.cfg_info = ssh_cfg_info,
|
||||
.test_for_upstream = ssh_test_for_upstream,
|
||||
.close_warn_text = ssh_close_warn_text,
|
||||
.description = ssh_backend_description,
|
||||
.id = "ssh",
|
||||
.displayname_tc = "SSH",
|
||||
.displayname_lc = "SSH", /* proper name, so capitalise it anyway */
|
||||
@ -1291,7 +1290,6 @@ const BackendVtable sshconn_backend = {
|
||||
.cfg_info = ssh_cfg_info,
|
||||
.test_for_upstream = ssh_test_for_upstream,
|
||||
.close_warn_text = ssh_close_warn_text,
|
||||
.description = ssh_backend_description,
|
||||
.id = "ssh-connection",
|
||||
.displayname_tc = "Bare ssh-connection",
|
||||
.displayname_lc = "bare ssh-connection",
|
||||
|
Loading…
Reference in New Issue
Block a user