2000-10-23 11:55:11 +00:00
|
|
|
/*
|
|
|
|
* Networking abstraction in PuTTY.
|
|
|
|
*
|
|
|
|
* The way this works is: a back end can choose to open any number
|
|
|
|
* of sockets - including zero, which might be necessary in some.
|
2019-09-08 19:29:00 +00:00
|
|
|
* It can register a bunch of callbacks (most notably for when
|
2001-03-13 10:22:45 +00:00
|
|
|
* data is received) for each socket, and it can call the networking
|
|
|
|
* abstraction to send data without having to worry about blocking.
|
|
|
|
* The stuff behind the abstraction takes care of selects and
|
|
|
|
* nonblocking writes and all that sort of painful gubbins.
|
2000-10-23 11:55:11 +00:00
|
|
|
*/
|
|
|
|
|
2000-10-24 10:47:49 +00:00
|
|
|
#ifndef PUTTY_NETWORK_H
|
|
|
|
#define PUTTY_NETWORK_H
|
|
|
|
|
2018-05-24 07:59:01 +00:00
|
|
|
#include "defs.h"
|
2003-01-12 15:26:10 +00:00
|
|
|
|
2018-10-05 06:24:16 +00:00
|
|
|
typedef struct SocketVtable SocketVtable;
|
|
|
|
typedef struct PlugVtable PlugVtable;
|
|
|
|
|
|
|
|
struct Socket {
|
|
|
|
const struct SocketVtable *vt;
|
|
|
|
};
|
|
|
|
|
2018-10-05 06:03:46 +00:00
|
|
|
struct SocketVtable {
|
Get rid of lots of implicit pointer types.
All the main backend structures - Ssh, Telnet, Pty, Serial etc - now
describe structure types themselves rather than pointers to them. The
same goes for the codebase-wide trait types Socket and Plug, and the
supporting types SockAddr and Pinger.
All those things that were typedefed as pointers are older types; the
newer ones have the explicit * at the point of use, because that's
what I now seem to be preferring. But whichever one of those is
better, inconsistently using a mixture of the two styles is worse, so
let's make everything consistent.
A few types are still implicitly pointers, such as Bignum and some of
the GSSAPI types; generally this is either because they have to be
void *, or because they're typedefed differently on different
platforms and aren't always pointers at all. Can't be helped. But I've
got rid of the main ones, at least.
2018-10-04 18:10:23 +00:00
|
|
|
Plug *(*plug) (Socket *s, Plug *p);
|
2001-05-06 14:35:20 +00:00
|
|
|
/* use a different plug (return the old one) */
|
|
|
|
/* if p is NULL, it doesn't change the plug */
|
|
|
|
/* but it does return the one it's using */
|
Get rid of lots of implicit pointer types.
All the main backend structures - Ssh, Telnet, Pty, Serial etc - now
describe structure types themselves rather than pointers to them. The
same goes for the codebase-wide trait types Socket and Plug, and the
supporting types SockAddr and Pinger.
All those things that were typedefed as pointers are older types; the
newer ones have the explicit * at the point of use, because that's
what I now seem to be preferring. But whichever one of those is
better, inconsistently using a mixture of the two styles is worse, so
let's make everything consistent.
A few types are still implicitly pointers, such as Bignum and some of
the GSSAPI types; generally this is either because they have to be
void *, or because they're typedefed differently on different
platforms and aren't always pointers at all. Can't be helped. But I've
got rid of the main ones, at least.
2018-10-04 18:10:23 +00:00
|
|
|
void (*close) (Socket *s);
|
2019-02-06 20:42:44 +00:00
|
|
|
size_t (*write) (Socket *s, const void *data, size_t len);
|
|
|
|
size_t (*write_oob) (Socket *s, const void *data, size_t len);
|
Get rid of lots of implicit pointer types.
All the main backend structures - Ssh, Telnet, Pty, Serial etc - now
describe structure types themselves rather than pointers to them. The
same goes for the codebase-wide trait types Socket and Plug, and the
supporting types SockAddr and Pinger.
All those things that were typedefed as pointers are older types; the
newer ones have the explicit * at the point of use, because that's
what I now seem to be preferring. But whichever one of those is
better, inconsistently using a mixture of the two styles is worse, so
let's make everything consistent.
A few types are still implicitly pointers, such as Bignum and some of
the GSSAPI types; generally this is either because they have to be
void *, or because they're typedefed differently on different
platforms and aren't always pointers at all. Can't be helped. But I've
got rid of the main ones, at least.
2018-10-04 18:10:23 +00:00
|
|
|
void (*write_eof) (Socket *s);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
void (*set_frozen) (Socket *s, bool is_frozen);
|
2001-05-06 14:35:20 +00:00
|
|
|
/* ignored by tcp, but vital for ssl */
|
Get rid of lots of implicit pointer types.
All the main backend structures - Ssh, Telnet, Pty, Serial etc - now
describe structure types themselves rather than pointers to them. The
same goes for the codebase-wide trait types Socket and Plug, and the
supporting types SockAddr and Pinger.
All those things that were typedefed as pointers are older types; the
newer ones have the explicit * at the point of use, because that's
what I now seem to be preferring. But whichever one of those is
better, inconsistently using a mixture of the two styles is worse, so
let's make everything consistent.
A few types are still implicitly pointers, such as Bignum and some of
the GSSAPI types; generally this is either because they have to be
void *, or because they're typedefed differently on different
platforms and aren't always pointers at all. Can't be helped. But I've
got rid of the main ones, at least.
2018-10-04 18:10:23 +00:00
|
|
|
const char *(*socket_error) (Socket *s);
|
2024-06-26 05:47:53 +00:00
|
|
|
SocketEndpointInfo *(*endpoint_info) (Socket *s, bool peer);
|
2001-03-13 10:22:45 +00:00
|
|
|
};
|
|
|
|
|
2013-11-17 14:03:55 +00:00
|
|
|
typedef union { void *p; int i; } accept_ctx_t;
|
Get rid of lots of implicit pointer types.
All the main backend structures - Ssh, Telnet, Pty, Serial etc - now
describe structure types themselves rather than pointers to them. The
same goes for the codebase-wide trait types Socket and Plug, and the
supporting types SockAddr and Pinger.
All those things that were typedefed as pointers are older types; the
newer ones have the explicit * at the point of use, because that's
what I now seem to be preferring. But whichever one of those is
better, inconsistently using a mixture of the two styles is worse, so
let's make everything consistent.
A few types are still implicitly pointers, such as Bignum and some of
the GSSAPI types; generally this is either because they have to be
void *, or because they're typedefed differently on different
platforms and aren't always pointers at all. Can't be helped. But I've
got rid of the main ones, at least.
2018-10-04 18:10:23 +00:00
|
|
|
typedef Socket *(*accept_fn_t)(accept_ctx_t ctx, Plug *plug);
|
2013-11-17 14:03:55 +00:00
|
|
|
|
2018-10-05 06:24:16 +00:00
|
|
|
struct Plug {
|
|
|
|
const struct PlugVtable *vt;
|
|
|
|
};
|
|
|
|
|
2020-02-07 19:17:45 +00:00
|
|
|
typedef enum PlugLogType {
|
|
|
|
PLUGLOG_CONNECT_TRYING,
|
|
|
|
PLUGLOG_CONNECT_FAILED,
|
2020-02-07 19:18:50 +00:00
|
|
|
PLUGLOG_CONNECT_SUCCESS,
|
2020-02-07 19:17:45 +00:00
|
|
|
PLUGLOG_PROXY_MSG,
|
|
|
|
} PlugLogType;
|
|
|
|
|
New API for plug_closing() with a custom type enum.
Passing an operating-system-specific error code to plug_closing(),
such as errno or GetLastError(), was always a bit weird, given that it
generally had to be handled by cross-platform receiving code in
backends. I had the platform.h implementations #define any error
values that the cross-platform code would have to handle specially,
but that's still not a great system, because it also doesn't leave
freedom to invent error representations of my own that don't
correspond to any OS code. (For example, the ones I just removed from
proxy.h.)
So now, the OS error code is gone from the plug_closing API, and in
its place is a custom enumeration of closure types: normal, error, and
the special case BROKEN_PIPE which is the only OS error code we have
so far needed to handle specially. (All others just mean 'abandon the
connection and print the textual message'.)
Having already centralised the handling of OS error codes in the
previous commit, we've now got a convenient place to add any further
type codes for errors needing special handling: each of Unix
plug_closing_errno(), Windows plug_closing_system_error(), and Windows
plug_closing_winsock_error() can easily grow extra special cases if
need be, and each one will only have to live in one place.
2021-11-06 13:28:32 +00:00
|
|
|
typedef enum PlugCloseType {
|
|
|
|
PLUGCLOSE_NORMAL,
|
|
|
|
PLUGCLOSE_ERROR,
|
|
|
|
PLUGCLOSE_BROKEN_PIPE,
|
2021-11-06 13:31:09 +00:00
|
|
|
PLUGCLOSE_USER_ABORT,
|
New API for plug_closing() with a custom type enum.
Passing an operating-system-specific error code to plug_closing(),
such as errno or GetLastError(), was always a bit weird, given that it
generally had to be handled by cross-platform receiving code in
backends. I had the platform.h implementations #define any error
values that the cross-platform code would have to handle specially,
but that's still not a great system, because it also doesn't leave
freedom to invent error representations of my own that don't
correspond to any OS code. (For example, the ones I just removed from
proxy.h.)
So now, the OS error code is gone from the plug_closing API, and in
its place is a custom enumeration of closure types: normal, error, and
the special case BROKEN_PIPE which is the only OS error code we have
so far needed to handle specially. (All others just mean 'abandon the
connection and print the textual message'.)
Having already centralised the handling of OS error codes in the
previous commit, we've now got a convenient place to add any further
type codes for errors needing special handling: each of Unix
plug_closing_errno(), Windows plug_closing_system_error(), and Windows
plug_closing_winsock_error() can easily grow extra special cases if
need be, and each one will only have to live in one place.
2021-11-06 13:28:32 +00:00
|
|
|
} PlugCloseType;
|
|
|
|
|
2018-10-05 06:03:46 +00:00
|
|
|
struct PlugVtable {
|
2005-01-16 14:29:34 +00:00
|
|
|
/*
|
|
|
|
* Passes the client progress reports on the process of setting
|
|
|
|
* up the connection.
|
2019-09-08 19:29:00 +00:00
|
|
|
*
|
2020-02-07 19:17:45 +00:00
|
|
|
* - PLUGLOG_CONNECT_TRYING means we are about to try to connect
|
|
|
|
* to address `addr' (error_msg and error_code are ignored)
|
|
|
|
*
|
|
|
|
* - PLUGLOG_CONNECT_FAILED means we have failed to connect to
|
|
|
|
* address `addr' (error_msg and error_code are supplied). This
|
|
|
|
* is not a fatal error - we may well have other candidate
|
|
|
|
* addresses to fall back to. When it _is_ fatal, the closing()
|
2019-09-08 19:29:00 +00:00
|
|
|
* function will be called.
|
2020-02-07 19:17:45 +00:00
|
|
|
*
|
2021-09-13 13:28:47 +00:00
|
|
|
* - PLUGLOG_CONNECT_SUCCESS means we have succeeded in making a
|
|
|
|
* connection. `addr' gives the address we connected to, if
|
|
|
|
* available. (But sometimes, in cases of complicated proxy
|
|
|
|
* setups, it might not be available, so receivers of this log
|
|
|
|
* event should be prepared to deal with addr==NULL.)
|
2020-02-07 19:18:50 +00:00
|
|
|
*
|
2020-02-07 19:17:45 +00:00
|
|
|
* - PLUGLOG_PROXY_MSG means that error_msg contains a line of
|
|
|
|
* logging information from whatever the connection is being
|
|
|
|
* proxied through. This will typically be a wodge of
|
|
|
|
* standard-error output from a local proxy command, so the
|
|
|
|
* receiver should probably prefix it to indicate this.
|
2021-09-15 12:48:30 +00:00
|
|
|
*
|
|
|
|
* Note that sometimes log messages may be sent even to Socket
|
|
|
|
* types that don't involve making an outgoing connection, e.g.
|
|
|
|
* because the same core implementation (such as Windows handle
|
|
|
|
* sockets) is shared between listening and connecting sockets. So
|
|
|
|
* all Plugs must implement this method, even if only to ignore
|
|
|
|
* the logged events.
|
2005-01-16 14:29:34 +00:00
|
|
|
*/
|
2021-10-23 17:09:25 +00:00
|
|
|
void (*log)(Plug *p, PlugLogType type, SockAddr *addr, int port,
|
|
|
|
const char *error_msg, int error_code);
|
|
|
|
|
2001-05-06 14:35:20 +00:00
|
|
|
/*
|
New API for plug_closing() with a custom type enum.
Passing an operating-system-specific error code to plug_closing(),
such as errno or GetLastError(), was always a bit weird, given that it
generally had to be handled by cross-platform receiving code in
backends. I had the platform.h implementations #define any error
values that the cross-platform code would have to handle specially,
but that's still not a great system, because it also doesn't leave
freedom to invent error representations of my own that don't
correspond to any OS code. (For example, the ones I just removed from
proxy.h.)
So now, the OS error code is gone from the plug_closing API, and in
its place is a custom enumeration of closure types: normal, error, and
the special case BROKEN_PIPE which is the only OS error code we have
so far needed to handle specially. (All others just mean 'abandon the
connection and print the textual message'.)
Having already centralised the handling of OS error codes in the
previous commit, we've now got a convenient place to add any further
type codes for errors needing special handling: each of Unix
plug_closing_errno(), Windows plug_closing_system_error(), and Windows
plug_closing_winsock_error() can easily grow extra special cases if
need be, and each one will only have to live in one place.
2021-11-06 13:28:32 +00:00
|
|
|
* Notifies the Plug that the socket is closing, and something
|
|
|
|
* about why.
|
|
|
|
*
|
|
|
|
* - PLUGCLOSE_NORMAL means an ordinary non-error closure. In
|
|
|
|
* this case, error_msg should be ignored (and hopefully
|
|
|
|
* callers will have passed NULL).
|
2021-10-23 17:09:25 +00:00
|
|
|
*
|
New API for plug_closing() with a custom type enum.
Passing an operating-system-specific error code to plug_closing(),
such as errno or GetLastError(), was always a bit weird, given that it
generally had to be handled by cross-platform receiving code in
backends. I had the platform.h implementations #define any error
values that the cross-platform code would have to handle specially,
but that's still not a great system, because it also doesn't leave
freedom to invent error representations of my own that don't
correspond to any OS code. (For example, the ones I just removed from
proxy.h.)
So now, the OS error code is gone from the plug_closing API, and in
its place is a custom enumeration of closure types: normal, error, and
the special case BROKEN_PIPE which is the only OS error code we have
so far needed to handle specially. (All others just mean 'abandon the
connection and print the textual message'.)
Having already centralised the handling of OS error codes in the
previous commit, we've now got a convenient place to add any further
type codes for errors needing special handling: each of Unix
plug_closing_errno(), Windows plug_closing_system_error(), and Windows
plug_closing_winsock_error() can easily grow extra special cases if
need be, and each one will only have to live in one place.
2021-11-06 13:28:32 +00:00
|
|
|
* - PLUGCLOSE_ERROR indicates that an OS error occurred, and
|
|
|
|
* 'error_msg' contains a string describing it, for use in
|
|
|
|
* diagnostics. (Ownership of the string is not transferred.)
|
|
|
|
* This error class covers anything other than the special
|
|
|
|
* case below:
|
2021-10-23 17:09:25 +00:00
|
|
|
*
|
New API for plug_closing() with a custom type enum.
Passing an operating-system-specific error code to plug_closing(),
such as errno or GetLastError(), was always a bit weird, given that it
generally had to be handled by cross-platform receiving code in
backends. I had the platform.h implementations #define any error
values that the cross-platform code would have to handle specially,
but that's still not a great system, because it also doesn't leave
freedom to invent error representations of my own that don't
correspond to any OS code. (For example, the ones I just removed from
proxy.h.)
So now, the OS error code is gone from the plug_closing API, and in
its place is a custom enumeration of closure types: normal, error, and
the special case BROKEN_PIPE which is the only OS error code we have
so far needed to handle specially. (All others just mean 'abandon the
connection and print the textual message'.)
Having already centralised the handling of OS error codes in the
previous commit, we've now got a convenient place to add any further
type codes for errors needing special handling: each of Unix
plug_closing_errno(), Windows plug_closing_system_error(), and Windows
plug_closing_winsock_error() can easily grow extra special cases if
need be, and each one will only have to live in one place.
2021-11-06 13:28:32 +00:00
|
|
|
* - PLUGCLOSE_BROKEN_PIPE behaves like PLUGCLOSE_ERROR (in
|
|
|
|
* particular, there's still an error message provided), but
|
|
|
|
* distinguishes the particular error condition signalled by
|
|
|
|
* EPIPE / ERROR_BROKEN_PIPE, which ssh/sharing.c needs to
|
|
|
|
* recognise and handle specially in one situation.
|
2021-11-06 13:31:09 +00:00
|
|
|
*
|
|
|
|
* - PLUGCLOSE_USER_ABORT means that the close has happened as a
|
|
|
|
* result of some kind of deliberate user action (e.g. hitting
|
|
|
|
* ^C at a password prompt presented by a proxy socket setup
|
|
|
|
* phase). This can be used to suppress interactive error
|
|
|
|
* messages sent to the user (such as dialog boxes), on the
|
|
|
|
* grounds that the user already knows. However, 'error_msg'
|
|
|
|
* will still contain some appropriate text, so that
|
|
|
|
* non-interactive error reporting (e.g. event logs) can still
|
|
|
|
* record why the connection terminated.
|
2021-10-23 17:09:25 +00:00
|
|
|
*/
|
New API for plug_closing() with a custom type enum.
Passing an operating-system-specific error code to plug_closing(),
such as errno or GetLastError(), was always a bit weird, given that it
generally had to be handled by cross-platform receiving code in
backends. I had the platform.h implementations #define any error
values that the cross-platform code would have to handle specially,
but that's still not a great system, because it also doesn't leave
freedom to invent error representations of my own that don't
correspond to any OS code. (For example, the ones I just removed from
proxy.h.)
So now, the OS error code is gone from the plug_closing API, and in
its place is a custom enumeration of closure types: normal, error, and
the special case BROKEN_PIPE which is the only OS error code we have
so far needed to handle specially. (All others just mean 'abandon the
connection and print the textual message'.)
Having already centralised the handling of OS error codes in the
previous commit, we've now got a convenient place to add any further
type codes for errors needing special handling: each of Unix
plug_closing_errno(), Windows plug_closing_system_error(), and Windows
plug_closing_winsock_error() can easily grow extra special cases if
need be, and each one will only have to live in one place.
2021-11-06 13:28:32 +00:00
|
|
|
void (*closing)(Plug *p, PlugCloseType type, const char *error_msg);
|
2021-10-23 17:09:25 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Provides incoming socket data to the Plug. Three cases:
|
|
|
|
*
|
2001-05-06 14:35:20 +00:00
|
|
|
* - urgent==0. `data' points to `len' bytes of perfectly
|
|
|
|
* ordinary data.
|
2019-09-08 19:29:00 +00:00
|
|
|
*
|
2001-05-06 14:35:20 +00:00
|
|
|
* - urgent==1. `data' points to `len' bytes of data,
|
|
|
|
* which were read from before an Urgent pointer.
|
2019-09-08 19:29:00 +00:00
|
|
|
*
|
2001-05-06 14:35:20 +00:00
|
|
|
* - urgent==2. `data' points to `len' bytes of data,
|
|
|
|
* the first of which was the one at the Urgent mark.
|
|
|
|
*/
|
2021-10-23 17:09:25 +00:00
|
|
|
void (*receive) (Plug *p, int urgent, const char *data, size_t len);
|
|
|
|
|
2001-08-25 17:09:23 +00:00
|
|
|
/*
|
2021-10-23 17:09:25 +00:00
|
|
|
* Called when the pending send backlog on a socket is cleared or
|
|
|
|
* partially cleared. The new backlog size is passed in the
|
|
|
|
* `bufsize' parameter.
|
2001-08-25 17:09:23 +00:00
|
|
|
*/
|
2021-10-23 17:09:25 +00:00
|
|
|
void (*sent) (Plug *p, size_t bufsize);
|
|
|
|
|
2001-08-08 20:44:35 +00:00
|
|
|
/*
|
2021-10-23 17:09:25 +00:00
|
|
|
* Only called on listener-type sockets, and is passed a
|
|
|
|
* constructor function+context that will create a fresh Socket
|
|
|
|
* describing the connection. It returns nonzero if it doesn't
|
|
|
|
* want the connection for some reason, or 0 on success.
|
2001-08-08 20:44:35 +00:00
|
|
|
*/
|
2021-10-23 17:09:25 +00:00
|
|
|
int (*accepting)(Plug *p, accept_fn_t constructor, accept_ctx_t ctx);
|
2001-03-13 10:22:45 +00:00
|
|
|
};
|
2001-01-24 10:11:18 +00:00
|
|
|
|
2021-09-13 16:17:20 +00:00
|
|
|
/* Proxy indirection layer.
|
|
|
|
*
|
|
|
|
* Calling new_connection transfers ownership of 'addr': the proxy
|
|
|
|
* layer is now responsible for freeing it, and the caller shouldn't
|
|
|
|
* assume it exists any more.
|
|
|
|
*
|
Allow new_connection to take an optional Seat. (NFC)
This is working towards allowing the subsidiary SSH connection in an
SshProxy to share the main user-facing Seat, so as to be able to pass
through interactive prompts.
This is more difficult than the similar change with LogPolicy, because
Seats are stateful. In particular, the trust-sigil status will need to
be controlled by the SshProxy until it's ready to pass over control to
the main SSH (or whatever) connection.
To make this work, I've introduced a thing called a TempSeat, which is
(yet) another Seat implementation. When a backend hands its Seat to
new_connection(), it does it in a way that allows new_connection() to
borrow it completely, and replace it in the main backend structure
with a TempSeat, which acts as a temporary placeholder. If the main
backend tries to do things like changing trust status or sending
output, the TempSeat will buffer them; later on, when the connection
is established, TempSeat will replay the changes into the real Seat.
So, in each backend, I've made the following changes:
- pass &foo->seat to new_connection, which may overwrite it with a
TempSeat.
- if it has done so (which we can tell via the is_tempseat() query
function), then we have to free the TempSeat and reinstate our main
Seat. The signal that we can do so is the PLUGLOG_CONNECT_SUCCESS
notification, which indicates that SshProxy has finished all its
connection setup work.
- we also have to remember to free the TempSeat if our backend is
disposed of without that having happened (e.g. because the
connection _doesn't_ succeed).
- in backends which have no local auth phase to worry about, ensure
we don't call seat_set_trust_status on the main Seat _before_ it
gets potentially replaced with a TempSeat. Moved some calls of
seat_set_trust_status to just after new_connection(), so that now
the initial trust status setup will go into the TempSeat (if
appropriate) and be buffered until that seat is relinquished.
In all other uses of new_connection, where we don't have a Seat
available at all, we just pass NULL.
This is NFC, because neither new_connection() nor any of its delegates
will _actually_ do this replacement yet. We're just setting up the
framework to enable it to do so in the next commit.
2021-09-13 16:17:20 +00:00
|
|
|
* If calling this from a backend with a Seat, you can also give it a
|
2021-10-30 16:36:52 +00:00
|
|
|
* pointer to the backend's Interactor trait. In that situation, it
|
|
|
|
* might replace the backend's seat with a temporary seat of its own,
|
|
|
|
* and give the real Seat to an Interactor somewhere in the proxy
|
|
|
|
* system so that it can ask for passwords (and, in the case of SSH
|
|
|
|
* proxying, other prompts like host key checks). If that happens,
|
|
|
|
* then the resulting 'temp seat' is the backend's property, and it
|
|
|
|
* will have to remember to free it when cleaning up, or after
|
Allow new_connection to take an optional Seat. (NFC)
This is working towards allowing the subsidiary SSH connection in an
SshProxy to share the main user-facing Seat, so as to be able to pass
through interactive prompts.
This is more difficult than the similar change with LogPolicy, because
Seats are stateful. In particular, the trust-sigil status will need to
be controlled by the SshProxy until it's ready to pass over control to
the main SSH (or whatever) connection.
To make this work, I've introduced a thing called a TempSeat, which is
(yet) another Seat implementation. When a backend hands its Seat to
new_connection(), it does it in a way that allows new_connection() to
borrow it completely, and replace it in the main backend structure
with a TempSeat, which acts as a temporary placeholder. If the main
backend tries to do things like changing trust status or sending
output, the TempSeat will buffer them; later on, when the connection
is established, TempSeat will replay the changes into the real Seat.
So, in each backend, I've made the following changes:
- pass &foo->seat to new_connection, which may overwrite it with a
TempSeat.
- if it has done so (which we can tell via the is_tempseat() query
function), then we have to free the TempSeat and reinstate our main
Seat. The signal that we can do so is the PLUGLOG_CONNECT_SUCCESS
notification, which indicates that SshProxy has finished all its
connection setup work.
- we also have to remember to free the TempSeat if our backend is
disposed of without that having happened (e.g. because the
connection _doesn't_ succeed).
- in backends which have no local auth phase to worry about, ensure
we don't call seat_set_trust_status on the main Seat _before_ it
gets potentially replaced with a TempSeat. Moved some calls of
seat_set_trust_status to just after new_connection(), so that now
the initial trust status setup will go into the TempSeat (if
appropriate) and be buffered until that seat is relinquished.
In all other uses of new_connection, where we don't have a Seat
available at all, we just pass NULL.
This is NFC, because neither new_connection() nor any of its delegates
will _actually_ do this replacement yet. We're just setting up the
framework to enable it to do so in the next commit.
2021-09-13 16:17:20 +00:00
|
|
|
* flushing it back into the real seat when the network connection
|
|
|
|
* attempt completes.
|
|
|
|
*
|
|
|
|
* You can free your TempSeat and resume using the real Seat when one
|
|
|
|
* of two things happens: either your Plug's closing() method is
|
|
|
|
* called (indicating failure to connect), or its log() method is
|
|
|
|
* called with PLUGLOG_CONNECT_SUCCESS. In the latter case, you'll
|
|
|
|
* probably want to flush the TempSeat's contents into the real Seat,
|
|
|
|
* of course.
|
2021-09-13 16:17:20 +00:00
|
|
|
*/
|
Get rid of lots of implicit pointer types.
All the main backend structures - Ssh, Telnet, Pty, Serial etc - now
describe structure types themselves rather than pointers to them. The
same goes for the codebase-wide trait types Socket and Plug, and the
supporting types SockAddr and Pinger.
All those things that were typedefed as pointers are older types; the
newer ones have the explicit * at the point of use, because that's
what I now seem to be preferring. But whichever one of those is
better, inconsistently using a mixture of the two styles is worse, so
let's make everything consistent.
A few types are still implicitly pointers, such as Bignum and some of
the GSSAPI types; generally this is either because they have to be
void *, or because they're typedefed differently on different
platforms and aren't always pointers at all. Can't be helped. But I've
got rid of the main ones, at least.
2018-10-04 18:10:23 +00:00
|
|
|
Socket *new_connection(SockAddr *addr, const char *hostname,
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
int port, bool privport,
|
|
|
|
bool oobinline, bool nodelay, bool keepalive,
|
2021-10-30 16:36:52 +00:00
|
|
|
Plug *plug, Conf *conf, Interactor *interactor);
|
Get rid of lots of implicit pointer types.
All the main backend structures - Ssh, Telnet, Pty, Serial etc - now
describe structure types themselves rather than pointers to them. The
same goes for the codebase-wide trait types Socket and Plug, and the
supporting types SockAddr and Pinger.
All those things that were typedefed as pointers are older types; the
newer ones have the explicit * at the point of use, because that's
what I now seem to be preferring. But whichever one of those is
better, inconsistently using a mixture of the two styles is worse, so
let's make everything consistent.
A few types are still implicitly pointers, such as Bignum and some of
the GSSAPI types; generally this is either because they have to be
void *, or because they're typedefed differently on different
platforms and aren't always pointers at all. Can't be helped. But I've
got rid of the main ones, at least.
2018-10-04 18:10:23 +00:00
|
|
|
Socket *new_listener(const char *srcaddr, int port, Plug *plug,
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool local_host_only, Conf *conf, int addressfamily);
|
Get rid of lots of implicit pointer types.
All the main backend structures - Ssh, Telnet, Pty, Serial etc - now
describe structure types themselves rather than pointers to them. The
same goes for the codebase-wide trait types Socket and Plug, and the
supporting types SockAddr and Pinger.
All those things that were typedefed as pointers are older types; the
newer ones have the explicit * at the point of use, because that's
what I now seem to be preferring. But whichever one of those is
better, inconsistently using a mixture of the two styles is worse, so
let's make everything consistent.
A few types are still implicitly pointers, such as Bignum and some of
the GSSAPI types; generally this is either because they have to be
void *, or because they're typedefed differently on different
platforms and aren't always pointers at all. Can't be helped. But I've
got rid of the main ones, at least.
2018-10-04 18:10:23 +00:00
|
|
|
SockAddr *name_lookup(const char *host, int port, char **canonicalname,
|
Refactor the LogContext type.
LogContext is now the owner of the logevent() function that back ends
and so forth are constantly calling. Previously, logevent was owned by
the Frontend, which would store the message into its list for the GUI
Event Log dialog (or print it to standard error, or whatever) and then
pass it _back_ to LogContext to write to the currently open log file.
Now it's the other way round: LogContext gets the message from the
back end first, writes it to its log file if it feels so inclined, and
communicates it back to the front end.
This means that lots of parts of the back end system no longer need to
have a pointer to a full-on Frontend; the only thing they needed it
for was logging, so now they just have a LogContext (which many of
them had to have anyway, e.g. for logging SSH packets or session
traffic).
LogContext itself also doesn't get a full Frontend pointer any more:
it now talks back to the front end via a little vtable of its own
called LogPolicy, which contains the method that passes Event Log
entries through, the old askappend() function that decides whether to
truncate a pre-existing log file, and an emergency function for
printing an especially prominent message if the log file can't be
created. One minor nice effect of this is that console and GUI apps
can implement that last function subtly differently, so that Unix
console apps can write it with a plain \n instead of the \r\n
(harmless but inelegant) that the old centralised implementation
generated.
One other consequence of this is that the LogContext has to be
provided to backend_init() so that it's available to backends from the
instant of creation, rather than being provided via a separate API
call a couple of function calls later, because backends have typically
started doing things that need logging (like making network
connections) before the call to backend_provide_logctx. Fortunately,
there's no case in the whole code base where we don't already have
logctx by the time we make a backend (so I don't actually remember why
I ever delayed providing one). So that shortens the backend API by one
function, which is always nice.
While I'm tidying up, I've also moved the printf-style logeventf() and
the handy logevent_and_free() into logging.c, instead of having copies
of them scattered around other places. This has also let me remove
some stub functions from a couple of outlying applications like
Pageant. Finally, I've removed the pointless "_tag" at the end of
LogContext's official struct name.
2018-10-10 18:26:18 +00:00
|
|
|
Conf *conf, int addressfamily, LogContext *logctx,
|
Get rid of lots of implicit pointer types.
All the main backend structures - Ssh, Telnet, Pty, Serial etc - now
describe structure types themselves rather than pointers to them. The
same goes for the codebase-wide trait types Socket and Plug, and the
supporting types SockAddr and Pinger.
All those things that were typedefed as pointers are older types; the
newer ones have the explicit * at the point of use, because that's
what I now seem to be preferring. But whichever one of those is
better, inconsistently using a mixture of the two styles is worse, so
let's make everything consistent.
A few types are still implicitly pointers, such as Bignum and some of
the GSSAPI types; generally this is either because they have to be
void *, or because they're typedefed differently on different
platforms and aren't always pointers at all. Can't be helped. But I've
got rid of the main ones, at least.
2018-10-04 18:10:23 +00:00
|
|
|
const char *lookup_reason_for_logging);
|
2002-03-23 17:47:21 +00:00
|
|
|
|
2003-06-06 10:42:14 +00:00
|
|
|
/* platform-dependent callback from new_connection() */
|
2003-08-07 16:04:33 +00:00
|
|
|
/* (same caveat about addr as new_connection()) */
|
Get rid of lots of implicit pointer types.
All the main backend structures - Ssh, Telnet, Pty, Serial etc - now
describe structure types themselves rather than pointers to them. The
same goes for the codebase-wide trait types Socket and Plug, and the
supporting types SockAddr and Pinger.
All those things that were typedefed as pointers are older types; the
newer ones have the explicit * at the point of use, because that's
what I now seem to be preferring. But whichever one of those is
better, inconsistently using a mixture of the two styles is worse, so
let's make everything consistent.
A few types are still implicitly pointers, such as Bignum and some of
the GSSAPI types; generally this is either because they have to be
void *, or because they're typedefed differently on different
platforms and aren't always pointers at all. Can't be helped. But I've
got rid of the main ones, at least.
2018-10-04 18:10:23 +00:00
|
|
|
Socket *platform_new_connection(SockAddr *addr, const char *hostname,
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
int port, bool privport,
|
|
|
|
bool oobinline, bool nodelay, bool keepalive,
|
2021-12-21 13:35:51 +00:00
|
|
|
Plug *plug, Conf *conf, Interactor *itr);
|
2003-06-06 10:42:14 +00:00
|
|
|
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
/* callback for SSH jump-host proxying */
|
|
|
|
Socket *sshproxy_new_connection(SockAddr *addr, const char *hostname,
|
|
|
|
int port, bool privport,
|
|
|
|
bool oobinline, bool nodelay, bool keepalive,
|
2021-10-30 16:36:52 +00:00
|
|
|
Plug *plug, Conf *conf, Interactor *itr);
|
Initial support for in-process proxy SSH connections.
This introduces a new entry to the radio-button list of proxy types,
in which the 'Proxy host' box is taken to be the name of an SSH server
or saved session. We make an entire subsidiary SSH connection to that
host, open a direct-tcpip channel through it, and use that as the
connection over which to run the primary network connection.
The result is basically the same as if you used a local proxy
subprocess, with a command along the lines of 'plink -batch %proxyhost
-nc %host:%port'. But it's all done in-process, by having an SshProxy
object implement the Socket trait to talk to the main connection, and
implement Seat and LogPolicy to talk to its subsidiary SSH backend.
All the refactoring in recent years has got us to the point where we
can do that without both SSH instances fighting over some global
variable or unique piece of infrastructure.
From an end user perspective, doing SSH proxying in-process like this
is a little bit easier to set up: it doesn't require you to bake the
full pathname of Plink into your saved session (or to have it on the
system PATH), and the SshProxy setup function automatically turns off
SSH features that would be inappropriate in this context, such as
additional port forwardings, or acting as a connection-sharing
upstream. And it has minor advantages like getting the Event Log for
the subsidiary connection interleaved in the main Event Log, as if it
were stderr output from a proxy subcommand, without having to
deliberately configure the subsidiary Plink into verbose mode.
However, this is an initial implementation only, and it doesn't yet
support the _big_ payoff for doing this in-process, which (I hope)
will be the ability to handle interactive prompts from the subsidiary
SSH connection via the same user interface as the primary one. For
example, you might need to answer two password prompts in succession,
or (the first time you use a session configured this way) confirm the
host keys for both proxy and destination SSH servers. Comments in the
new source file discuss some design thoughts on filling in this gap.
For the moment, if the proxy SSH connection encounters any situation
where an interactive prompt is needed, it will make the safe
assumption, the same way 'plink -batch' would do. So it's at least no
_worse_ than the existing technique of putting the proxy connection in
a subprocess.
2021-05-22 11:51:23 +00:00
|
|
|
|
2002-03-23 17:47:21 +00:00
|
|
|
/* socket functions */
|
2000-10-23 11:55:11 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
void sk_init(void); /* called once at program startup */
|
|
|
|
void sk_cleanup(void); /* called just before program exit */
|
2000-10-23 11:55:11 +00:00
|
|
|
|
Get rid of lots of implicit pointer types.
All the main backend structures - Ssh, Telnet, Pty, Serial etc - now
describe structure types themselves rather than pointers to them. The
same goes for the codebase-wide trait types Socket and Plug, and the
supporting types SockAddr and Pinger.
All those things that were typedefed as pointers are older types; the
newer ones have the explicit * at the point of use, because that's
what I now seem to be preferring. But whichever one of those is
better, inconsistently using a mixture of the two styles is worse, so
let's make everything consistent.
A few types are still implicitly pointers, such as Bignum and some of
the GSSAPI types; generally this is either because they have to be
void *, or because they're typedefed differently on different
platforms and aren't always pointers at all. Can't be helped. But I've
got rid of the main ones, at least.
2018-10-04 18:10:23 +00:00
|
|
|
SockAddr *sk_namelookup(const char *host, char **canonicalname, int address_family);
|
|
|
|
SockAddr *sk_nonamelookup(const char *host);
|
|
|
|
void sk_getaddr(SockAddr *addr, char *buf, int buflen);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool sk_addr_needs_port(SockAddr *addr);
|
|
|
|
bool sk_hostname_is_local(const char *name);
|
|
|
|
bool sk_address_is_local(SockAddr *addr);
|
|
|
|
bool sk_address_is_special_local(SockAddr *addr);
|
Get rid of lots of implicit pointer types.
All the main backend structures - Ssh, Telnet, Pty, Serial etc - now
describe structure types themselves rather than pointers to them. The
same goes for the codebase-wide trait types Socket and Plug, and the
supporting types SockAddr and Pinger.
All those things that were typedefed as pointers are older types; the
newer ones have the explicit * at the point of use, because that's
what I now seem to be preferring. But whichever one of those is
better, inconsistently using a mixture of the two styles is worse, so
let's make everything consistent.
A few types are still implicitly pointers, such as Bignum and some of
the GSSAPI types; generally this is either because they have to be
void *, or because they're typedefed differently on different
platforms and aren't always pointers at all. Can't be helped. But I've
got rid of the main ones, at least.
2018-10-04 18:10:23 +00:00
|
|
|
int sk_addrtype(SockAddr *addr);
|
|
|
|
void sk_addrcopy(SockAddr *addr, char *buf);
|
|
|
|
void sk_addr_free(SockAddr *addr);
|
2008-11-08 16:58:55 +00:00
|
|
|
/* sk_addr_dup generates another SockAddr which contains the same data
|
|
|
|
* as the original one and can be freed independently. May not actually
|
|
|
|
* physically _duplicate_ it: incrementing a reference count so that
|
|
|
|
* one more free is required before it disappears is an acceptable
|
|
|
|
* implementation. */
|
Get rid of lots of implicit pointer types.
All the main backend structures - Ssh, Telnet, Pty, Serial etc - now
describe structure types themselves rather than pointers to them. The
same goes for the codebase-wide trait types Socket and Plug, and the
supporting types SockAddr and Pinger.
All those things that were typedefed as pointers are older types; the
newer ones have the explicit * at the point of use, because that's
what I now seem to be preferring. But whichever one of those is
better, inconsistently using a mixture of the two styles is worse, so
let's make everything consistent.
A few types are still implicitly pointers, such as Bignum and some of
the GSSAPI types; generally this is either because they have to be
void *, or because they're typedefed differently on different
platforms and aren't always pointers at all. Can't be helped. But I've
got rid of the main ones, at least.
2018-10-04 18:10:23 +00:00
|
|
|
SockAddr *sk_addr_dup(SockAddr *addr);
|
2000-10-23 11:55:11 +00:00
|
|
|
|
2003-08-07 16:04:33 +00:00
|
|
|
/* NB, control of 'addr' is passed via sk_new, which takes responsibility
|
|
|
|
* for freeing it, as for new_connection() */
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
Socket *sk_new(SockAddr *addr, int port, bool privport, bool oobinline,
|
|
|
|
bool nodelay, bool keepalive, Plug *p);
|
2001-03-13 10:22:45 +00:00
|
|
|
|
Get rid of lots of implicit pointer types.
All the main backend structures - Ssh, Telnet, Pty, Serial etc - now
describe structure types themselves rather than pointers to them. The
same goes for the codebase-wide trait types Socket and Plug, and the
supporting types SockAddr and Pinger.
All those things that were typedefed as pointers are older types; the
newer ones have the explicit * at the point of use, because that's
what I now seem to be preferring. But whichever one of those is
better, inconsistently using a mixture of the two styles is worse, so
let's make everything consistent.
A few types are still implicitly pointers, such as Bignum and some of
the GSSAPI types; generally this is either because they have to be
void *, or because they're typedefed differently on different
platforms and aren't always pointers at all. Can't be helped. But I've
got rid of the main ones, at least.
2018-10-04 18:10:23 +00:00
|
|
|
Socket *sk_newlistener(const char *srcaddr, int port, Plug *plug,
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool local_host_only, int address_family);
|
2001-08-08 20:44:35 +00:00
|
|
|
|
2019-02-27 19:44:15 +00:00
|
|
|
static inline Plug *sk_plug(Socket *s, Plug *p)
|
|
|
|
{ return s->vt->plug(s, p); }
|
|
|
|
static inline void sk_close(Socket *s)
|
|
|
|
{ s->vt->close(s); }
|
|
|
|
static inline size_t sk_write(Socket *s, const void *data, size_t len)
|
|
|
|
{ return s->vt->write(s, data, len); }
|
|
|
|
static inline size_t sk_write_oob(Socket *s, const void *data, size_t len)
|
|
|
|
{ return s->vt->write_oob(s, data, len); }
|
|
|
|
static inline void sk_write_eof(Socket *s)
|
|
|
|
{ s->vt->write_eof(s); }
|
|
|
|
|
|
|
|
static inline void plug_log(
|
|
|
|
Plug *p, int type, SockAddr *addr, int port, const char *msg, int code)
|
2019-04-06 09:12:31 +00:00
|
|
|
{ p->vt->log(p, type, addr, port, msg, code); }
|
New API for plug_closing() with a custom type enum.
Passing an operating-system-specific error code to plug_closing(),
such as errno or GetLastError(), was always a bit weird, given that it
generally had to be handled by cross-platform receiving code in
backends. I had the platform.h implementations #define any error
values that the cross-platform code would have to handle specially,
but that's still not a great system, because it also doesn't leave
freedom to invent error representations of my own that don't
correspond to any OS code. (For example, the ones I just removed from
proxy.h.)
So now, the OS error code is gone from the plug_closing API, and in
its place is a custom enumeration of closure types: normal, error, and
the special case BROKEN_PIPE which is the only OS error code we have
so far needed to handle specially. (All others just mean 'abandon the
connection and print the textual message'.)
Having already centralised the handling of OS error codes in the
previous commit, we've now got a convenient place to add any further
type codes for errors needing special handling: each of Unix
plug_closing_errno(), Windows plug_closing_system_error(), and Windows
plug_closing_winsock_error() can easily grow extra special cases if
need be, and each one will only have to live in one place.
2021-11-06 13:28:32 +00:00
|
|
|
static inline void plug_closing(Plug *p, PlugCloseType type, const char *msg)
|
|
|
|
{ p->vt->closing(p, type, msg); }
|
Convenience wrappers on plug_closing().
Having a single plug_closing() function covering various kinds of
closure is reasonably convenient from the point of view of Plug
implementations, but it's annoying for callers, who all have to fill
in pointless NULL and 0 parameters in the cases where they're not
used.
Added some inline helper functions in network.h alongside the main
plug_closing() dispatch wrappers, so that each kind of connection
closure can present a separate API for the Socket side of the
interface, without complicating the vtable for the Plug side.
Also, added OS-specific extra helpers in the Unix and Windows
directories, which centralise the job of taking an OS error code (of
whatever kind) and translating it into its error message.
In passing, this removes the horrible ad-hoc made-up error codes in
proxy.h, which is OK, because nothing checked for them anyway, and
also I'm about to do an API change to plug_closing proper that removes
the need for them.
2021-11-06 13:25:42 +00:00
|
|
|
static inline void plug_closing_normal(Plug *p)
|
New API for plug_closing() with a custom type enum.
Passing an operating-system-specific error code to plug_closing(),
such as errno or GetLastError(), was always a bit weird, given that it
generally had to be handled by cross-platform receiving code in
backends. I had the platform.h implementations #define any error
values that the cross-platform code would have to handle specially,
but that's still not a great system, because it also doesn't leave
freedom to invent error representations of my own that don't
correspond to any OS code. (For example, the ones I just removed from
proxy.h.)
So now, the OS error code is gone from the plug_closing API, and in
its place is a custom enumeration of closure types: normal, error, and
the special case BROKEN_PIPE which is the only OS error code we have
so far needed to handle specially. (All others just mean 'abandon the
connection and print the textual message'.)
Having already centralised the handling of OS error codes in the
previous commit, we've now got a convenient place to add any further
type codes for errors needing special handling: each of Unix
plug_closing_errno(), Windows plug_closing_system_error(), and Windows
plug_closing_winsock_error() can easily grow extra special cases if
need be, and each one will only have to live in one place.
2021-11-06 13:28:32 +00:00
|
|
|
{ p->vt->closing(p, PLUGCLOSE_NORMAL, NULL); }
|
Convenience wrappers on plug_closing().
Having a single plug_closing() function covering various kinds of
closure is reasonably convenient from the point of view of Plug
implementations, but it's annoying for callers, who all have to fill
in pointless NULL and 0 parameters in the cases where they're not
used.
Added some inline helper functions in network.h alongside the main
plug_closing() dispatch wrappers, so that each kind of connection
closure can present a separate API for the Socket side of the
interface, without complicating the vtable for the Plug side.
Also, added OS-specific extra helpers in the Unix and Windows
directories, which centralise the job of taking an OS error code (of
whatever kind) and translating it into its error message.
In passing, this removes the horrible ad-hoc made-up error codes in
proxy.h, which is OK, because nothing checked for them anyway, and
also I'm about to do an API change to plug_closing proper that removes
the need for them.
2021-11-06 13:25:42 +00:00
|
|
|
static inline void plug_closing_error(Plug *p, const char *msg)
|
New API for plug_closing() with a custom type enum.
Passing an operating-system-specific error code to plug_closing(),
such as errno or GetLastError(), was always a bit weird, given that it
generally had to be handled by cross-platform receiving code in
backends. I had the platform.h implementations #define any error
values that the cross-platform code would have to handle specially,
but that's still not a great system, because it also doesn't leave
freedom to invent error representations of my own that don't
correspond to any OS code. (For example, the ones I just removed from
proxy.h.)
So now, the OS error code is gone from the plug_closing API, and in
its place is a custom enumeration of closure types: normal, error, and
the special case BROKEN_PIPE which is the only OS error code we have
so far needed to handle specially. (All others just mean 'abandon the
connection and print the textual message'.)
Having already centralised the handling of OS error codes in the
previous commit, we've now got a convenient place to add any further
type codes for errors needing special handling: each of Unix
plug_closing_errno(), Windows plug_closing_system_error(), and Windows
plug_closing_winsock_error() can easily grow extra special cases if
need be, and each one will only have to live in one place.
2021-11-06 13:28:32 +00:00
|
|
|
{ p->vt->closing(p, PLUGCLOSE_ERROR, msg); }
|
2021-11-06 13:31:09 +00:00
|
|
|
static inline void plug_closing_user_abort(Plug *p)
|
|
|
|
{ p->vt->closing(p, PLUGCLOSE_USER_ABORT, "User aborted connection setup"); }
|
2019-02-27 19:44:15 +00:00
|
|
|
static inline void plug_receive(Plug *p, int urg, const char *data, size_t len)
|
2019-04-06 09:12:31 +00:00
|
|
|
{ p->vt->receive(p, urg, data, len); }
|
2019-02-27 19:44:15 +00:00
|
|
|
static inline void plug_sent (Plug *p, size_t bufsize)
|
2019-04-06 09:12:31 +00:00
|
|
|
{ p->vt->sent(p, bufsize); }
|
2019-02-27 19:44:15 +00:00
|
|
|
static inline int plug_accepting(Plug *p, accept_fn_t cons, accept_ctx_t ctx)
|
|
|
|
{ return p->vt->accepting(p, cons, ctx); }
|
2000-10-23 11:55:11 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Special error values are returned from sk_namelookup and sk_new
|
|
|
|
* if there's a problem. These functions extract an error message,
|
|
|
|
* or return NULL if there's no problem.
|
|
|
|
*/
|
Get rid of lots of implicit pointer types.
All the main backend structures - Ssh, Telnet, Pty, Serial etc - now
describe structure types themselves rather than pointers to them. The
same goes for the codebase-wide trait types Socket and Plug, and the
supporting types SockAddr and Pinger.
All those things that were typedefed as pointers are older types; the
newer ones have the explicit * at the point of use, because that's
what I now seem to be preferring. But whichever one of those is
better, inconsistently using a mixture of the two styles is worse, so
let's make everything consistent.
A few types are still implicitly pointers, such as Bignum and some of
the GSSAPI types; generally this is either because they have to be
void *, or because they're typedefed differently on different
platforms and aren't always pointers at all. Can't be helped. But I've
got rid of the main ones, at least.
2018-10-04 18:10:23 +00:00
|
|
|
const char *sk_addr_error(SockAddr *addr);
|
2019-02-27 19:44:15 +00:00
|
|
|
static inline const char *sk_socket_error(Socket *s)
|
|
|
|
{ return s->vt->socket_error(s); }
|
2001-03-13 10:22:45 +00:00
|
|
|
|
2001-08-08 20:44:35 +00:00
|
|
|
/*
|
|
|
|
* Set the `frozen' flag on a socket. A frozen socket is one in
|
2001-08-25 17:09:23 +00:00
|
|
|
* which all READABLE notifications are ignored, so that data is
|
|
|
|
* not accepted from the peer until the socket is unfrozen. This
|
|
|
|
* exists for two purposes:
|
2019-09-08 19:29:00 +00:00
|
|
|
*
|
2001-08-25 17:09:23 +00:00
|
|
|
* - Port forwarding: when a local listening port receives a
|
|
|
|
* connection, we do not want to receive data from the new
|
|
|
|
* socket until we have somewhere to send it. Hence, we freeze
|
|
|
|
* the socket until its associated SSH channel is ready; then we
|
|
|
|
* unfreeze it and pending data is delivered.
|
2019-09-08 19:29:00 +00:00
|
|
|
*
|
2001-08-25 17:09:23 +00:00
|
|
|
* - Socket buffering: if an SSH channel (or the whole connection)
|
|
|
|
* backs up or presents a zero window, we must freeze the
|
|
|
|
* associated local socket in order to avoid unbounded buffer
|
|
|
|
* growth.
|
2001-08-08 20:44:35 +00:00
|
|
|
*/
|
2019-02-27 19:44:15 +00:00
|
|
|
static inline void sk_set_frozen(Socket *s, bool is_frozen)
|
|
|
|
{ s->vt->set_frozen(s, is_frozen); }
|
2001-03-13 10:22:45 +00:00
|
|
|
|
2015-05-18 12:57:45 +00:00
|
|
|
/*
|
2024-06-26 05:35:40 +00:00
|
|
|
* Return a structure giving some information about one end of
|
2018-10-18 19:06:42 +00:00
|
|
|
* the socket. May be NULL, if nothing is available at all. If it is
|
|
|
|
* not NULL, then it is dynamically allocated, and should be freed by
|
2024-06-26 05:35:40 +00:00
|
|
|
* a call to sk_free_endpoint_info(). See below for the definition.
|
2015-05-18 12:57:45 +00:00
|
|
|
*/
|
2024-06-26 05:47:53 +00:00
|
|
|
static inline SocketEndpointInfo *sk_endpoint_info(Socket *s, bool peer)
|
|
|
|
{ return s->vt->endpoint_info(s, peer); }
|
2024-06-26 05:35:40 +00:00
|
|
|
static inline SocketEndpointInfo *sk_peer_info(Socket *s)
|
2024-06-26 05:47:53 +00:00
|
|
|
{ return sk_endpoint_info(s, true); }
|
2015-05-18 12:57:45 +00:00
|
|
|
|
2018-10-18 19:06:42 +00:00
|
|
|
/*
|
2024-06-26 05:35:40 +00:00
|
|
|
* The structure returned from sk_endpoint_info, and a function to free
|
2022-01-22 15:38:53 +00:00
|
|
|
* one (in utils).
|
2018-10-18 19:06:42 +00:00
|
|
|
*/
|
2024-06-26 05:35:40 +00:00
|
|
|
struct SocketEndpointInfo {
|
2018-10-18 19:06:42 +00:00
|
|
|
int addressfamily;
|
|
|
|
|
|
|
|
/*
|
2024-06-26 05:35:40 +00:00
|
|
|
* Text form of the IPv4 or IPv6 address of the specified end of the
|
2018-10-18 19:06:42 +00:00
|
|
|
* socket, if available, in the standard text representation.
|
|
|
|
*/
|
|
|
|
const char *addr_text;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Binary form of the same address. Filled in if and only if
|
|
|
|
* addr_text is not NULL. You can tell which branch of the union
|
|
|
|
* is used by examining 'addressfamily'.
|
|
|
|
*/
|
|
|
|
union {
|
|
|
|
unsigned char ipv6[16];
|
|
|
|
unsigned char ipv4[4];
|
|
|
|
} addr_bin;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Remote port number, or -1 if not available.
|
|
|
|
*/
|
|
|
|
int port;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Free-form text suitable for putting in log messages. For IP
|
|
|
|
* sockets, repeats the address and port information from above.
|
|
|
|
* But it can be completely different, e.g. for Unix-domain
|
|
|
|
* sockets it gives information about the uid, gid and pid of the
|
|
|
|
* connecting process.
|
|
|
|
*/
|
|
|
|
const char *log_text;
|
|
|
|
};
|
2024-06-26 05:35:40 +00:00
|
|
|
void sk_free_endpoint_info(SocketEndpointInfo *ei);
|
2018-10-18 19:06:42 +00:00
|
|
|
|
2002-10-30 17:57:31 +00:00
|
|
|
/*
|
2022-01-22 15:38:53 +00:00
|
|
|
* Simple wrapper on getservbyname(), needed by portfwd.c. Returns the
|
2002-10-30 17:57:31 +00:00
|
|
|
* port number, in host byte order (suitable for printf and so on).
|
|
|
|
* Returns 0 on failure. Any platform not supporting getservbyname
|
|
|
|
* can just return 0 - this function is not required to handle
|
|
|
|
* numeric port specifications.
|
|
|
|
*/
|
2022-01-22 15:45:00 +00:00
|
|
|
int net_service_lookup(const char *service);
|
2002-10-30 17:57:31 +00:00
|
|
|
|
Since r8305, Unix PuTTY has always "upgraded" an X11 display like "localhost:0"
to a Unix-domain socket. This typically works fine when PuTTY is run on the
same machine as the X server, but it's broken multi-hop X forwarding through
OpenSSH; when OpenSSH creates a proxy X server "localhost:10", it only listens
on TCP, not on a Unix-domain socket.
Instead, when deciding on the details of the display, we actively probe to see
if there's a Unix-domain socket we can use instead, and only use it if it's
there, falling back to the specified IP "localhost" if not.
Independently, when looking for local auth details in Xauthority for a
"localhost" TCP display, we prefer a matching Unix-domain entry, but will fall
back to an IP "localhost" entry (which would be unusual, but we don't trust a
Windows X server not to do it) -- this is a generalisation of the special case
added in r2538 (but removed in r8305, as the automatic upgrade masked the need
for it).
(This is now done in platform-independent code, so a side-effect is that
get_hostname() is now part of the networking abstraction on all platforms.)
[originally from svn r8462]
[r2538 == fda998324345ba50a913655754303ce8f0a4cfde]
[r8305 == ca6fc3a4daf51166a15693feffc967bee9e3f59a]
2009-02-24 01:01:23 +00:00
|
|
|
/*
|
|
|
|
* Look up the local hostname; return value needs freeing.
|
|
|
|
* May return NULL.
|
|
|
|
*/
|
|
|
|
char *get_hostname(void);
|
|
|
|
|
2013-11-17 14:03:36 +00:00
|
|
|
/*
|
|
|
|
* Trivial socket implementation which just stores an error. Found in
|
|
|
|
* errsock.c.
|
2020-01-01 18:58:11 +00:00
|
|
|
*
|
|
|
|
* The consume_string variant takes an already-formatted dynamically
|
|
|
|
* allocated string, and takes over ownership of that string.
|
2013-11-17 14:03:36 +00:00
|
|
|
*/
|
2020-01-26 14:49:31 +00:00
|
|
|
Socket *new_error_socket_fmt(Plug *plug, const char *fmt, ...)
|
|
|
|
PRINTF_LIKE(2, 3);
|
2020-01-01 18:58:11 +00:00
|
|
|
Socket *new_error_socket_consume_string(Plug *plug, char *errmsg);
|
2013-11-17 14:03:36 +00:00
|
|
|
|
2018-05-27 14:41:12 +00:00
|
|
|
/*
|
|
|
|
* Trivial plug that does absolutely nothing. Found in nullplug.c.
|
|
|
|
*/
|
2018-10-05 06:24:16 +00:00
|
|
|
extern Plug *const nullplug;
|
2018-05-27 14:41:12 +00:00
|
|
|
|
2021-09-15 12:48:30 +00:00
|
|
|
/*
|
|
|
|
* Some trivial no-op plug functions, also in nullplug.c; exposed here
|
|
|
|
* so that other Plug implementations can use them too.
|
|
|
|
*
|
|
|
|
* In particular, nullplug_log is useful to Plugs that don't need to
|
|
|
|
* worry about logging.
|
|
|
|
*/
|
|
|
|
void nullplug_log(Plug *plug, PlugLogType type, SockAddr *addr,
|
|
|
|
int port, const char *err_msg, int err_code);
|
New API for plug_closing() with a custom type enum.
Passing an operating-system-specific error code to plug_closing(),
such as errno or GetLastError(), was always a bit weird, given that it
generally had to be handled by cross-platform receiving code in
backends. I had the platform.h implementations #define any error
values that the cross-platform code would have to handle specially,
but that's still not a great system, because it also doesn't leave
freedom to invent error representations of my own that don't
correspond to any OS code. (For example, the ones I just removed from
proxy.h.)
So now, the OS error code is gone from the plug_closing API, and in
its place is a custom enumeration of closure types: normal, error, and
the special case BROKEN_PIPE which is the only OS error code we have
so far needed to handle specially. (All others just mean 'abandon the
connection and print the textual message'.)
Having already centralised the handling of OS error codes in the
previous commit, we've now got a convenient place to add any further
type codes for errors needing special handling: each of Unix
plug_closing_errno(), Windows plug_closing_system_error(), and Windows
plug_closing_winsock_error() can easily grow extra special cases if
need be, and each one will only have to live in one place.
2021-11-06 13:28:32 +00:00
|
|
|
void nullplug_closing(Plug *plug, PlugCloseType type, const char *error_msg);
|
2021-09-15 12:48:30 +00:00
|
|
|
void nullplug_receive(Plug *plug, int urgent, const char *data, size_t len);
|
|
|
|
void nullplug_sent(Plug *plug, size_t bufsize);
|
|
|
|
|
2015-11-22 11:49:14 +00:00
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
* Functions defined outside the network code, which have to be
|
|
|
|
* declared in this header file rather than the main putty.h because
|
|
|
|
* they use types defined here.
|
|
|
|
*/
|
|
|
|
|
New abstraction 'Seat', to pass to backends.
This is a new vtable-based abstraction which is passed to a backend in
place of Frontend, and it implements only the subset of the Frontend
functions needed by a backend. (Many other Frontend functions still
exist, notably the wide range of things called by terminal.c providing
platform-independent operations on the GUI terminal window.)
The purpose of making it a vtable is that this opens up the
possibility of creating a backend as an internal implementation detail
of some other activity, by providing just that one backend with a
custom Seat that implements the methods differently.
For example, this refactoring should make it feasible to directly
implement an SSH proxy type, aka the 'jump host' feature supported by
OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP
mode, and then expose the main channel of that as the Socket for the
primary connection'. (Which of course you can already do by spawning
'plink -nc' as a separate proxy process, but this would permit it in
the _same_ process without anything getting confused.)
I've centralised a full set of stub methods in misc.c for the new
abstraction, which allows me to get rid of several annoying stubs in
the previous code. Also, while I'm here, I've moved a lot of
duplicated modalfatalbox() type functions from application main
program files into wincons.c / uxcons.c, which I think saves
duplication overall. (A minor visible effect is that the prefixes on
those console-based fatal error messages will now be more consistent
between applications.)
2018-10-11 18:58:42 +00:00
|
|
|
void backend_socket_log(Seat *seat, LogContext *logctx,
|
2020-02-07 19:17:45 +00:00
|
|
|
PlugLogType type, SockAddr *addr, int port,
|
2015-11-22 14:33:28 +00:00
|
|
|
const char *error_msg, int error_code, Conf *conf,
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool session_started);
|
2019-03-01 19:18:31 +00:00
|
|
|
|
|
|
|
typedef struct ProxyStderrBuf {
|
|
|
|
char buf[8192];
|
|
|
|
size_t size;
|
2022-08-22 17:46:32 +00:00
|
|
|
const char *prefix; /* must be statically allocated */
|
2019-03-01 19:18:31 +00:00
|
|
|
} ProxyStderrBuf;
|
|
|
|
void psb_init(ProxyStderrBuf *psb);
|
2022-08-22 17:46:32 +00:00
|
|
|
void psb_set_prefix(ProxyStderrBuf *psb, const char *prefix);
|
2019-02-06 20:42:44 +00:00
|
|
|
void log_proxy_stderr(
|
2019-03-01 19:18:31 +00:00
|
|
|
Plug *plug, ProxyStderrBuf *psb, const void *vdata, size_t len);
|
2015-11-22 11:49:14 +00:00
|
|
|
|
Allow creating FdSocket/HandleSocket before the fds/handles.
Previously, a setup function returning one of these socket types (such
as platform_new_connection) had to do all its setup synchronously,
because if it was going to call make_fd_socket or make_handle_socket,
it had to have the actual fds or HANDLEs ready-made. If some kind of
asynchronous operation were needed before those fds become available,
there would be no way the function could achieve it, except by
becoming a whole extra permanent Socket wrapper layer.
Now there is, because you can make an FdSocket when you don't yet have
the fds, or a HandleSocket without the HANDLEs. Instead, you provide
an instance of the new trait 'DeferredSocketOpener', which is
responsible for setting in motion whatever asynchronous setup
procedure it needs, and when that finishes, calling back to
setup_fd_socket / setup_handle_socket to provide the missing pieces.
In the meantime, the FdSocket or HandleSocket will sit there inertly,
buffering any data the client might eagerly hand it via sk_write(),
and waiting for its setup to finish. When it does finish, buffered
data will be released.
In FdSocket, this is easy enough, because we were doing our own
buffering anyway - we called the uxsel system to find out when the fds
were readable/writable, and then wrote to them from our own bufchain.
So more or less all I had to do was make the try_send function do
nothing if the setup phase wasn't finished yet.
In HandleSocket, on the other hand, we're passing all our data to the
underlying handle-io.c system, and making _that_ deferrable in the
same way would be much more painful, because that's the place where
the scary threads live. So instead I've arranged it by replacing the
whole vtable, so that a deferred HandleSocket and a normal
HandleSocket are effectively separate trait implementations that can
share their state structure. And in fact that state struct itself now
contains a big anonymous union, containing one branch to go with each
vtable.
Nothing yet uses this system, but the next commit will do so.
2021-12-22 09:31:06 +00:00
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
* The DeferredSocketOpener trait. This is a thing that some Socket
|
|
|
|
* implementations may choose to own if they need to delay actually
|
|
|
|
* setting up the underlying connection. For example, sockets used in
|
|
|
|
* local-proxy handling (Unix FdSocket / Windows HandleSocket) might
|
|
|
|
* need to do this if they have to prompt the user interactively for
|
|
|
|
* parts of the command they'll run.
|
|
|
|
*
|
|
|
|
* Mostly, a DeferredSocketOpener implementation will keep to itself,
|
|
|
|
* arrange its own callbacks in order to do whatever setup it needs,
|
|
|
|
* and when it's ready, call back to its parent Socket via some
|
|
|
|
* implementation-specific API of its own. So the shared API here
|
|
|
|
* requires almost nothing: the only thing we need is a free function,
|
|
|
|
* so that if the owner of a Socket of this kind needs to close it
|
|
|
|
* before the deferred connection process is finished, the Socket can
|
|
|
|
* also clean up the DeferredSocketOpener dangling off it.
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct DeferredSocketOpener {
|
|
|
|
const DeferredSocketOpenerVtable *vt;
|
|
|
|
};
|
|
|
|
struct DeferredSocketOpenerVtable {
|
|
|
|
void (*free)(DeferredSocketOpener *);
|
|
|
|
};
|
|
|
|
static inline void deferred_socket_opener_free(DeferredSocketOpener *dso)
|
|
|
|
{ dso->vt->free(dso); }
|
|
|
|
|
2022-08-22 17:46:32 +00:00
|
|
|
DeferredSocketOpener *null_deferred_socket_opener(void);
|
|
|
|
|
2000-10-24 10:47:49 +00:00
|
|
|
#endif
|