mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 09:27:59 +00:00
Centralise implementations of Windows do_select().
Windows Plink and PSFTP had very similar implementations, and now they share one that lives in a new file winselcli.c. I've similarly moved GUI PuTTY's implementation out of window.c into winselgui.c, where other GUI programs wanting to do networking will be able to access that too. In the spirit of centralisation, I've also taken the opportunity to make both functions use the reasonably complete winsock_error_string() rather than (for some historical reason) each inlining a minimal version that reports most errors as 'unknown'.
This commit is contained in:
parent
ae1148267d
commit
b89d17fbca
8
Recipe
8
Recipe
@ -244,7 +244,7 @@ TERMINAL = terminal stripctrl wcwidth logging tree234 minibidi
|
||||
|
||||
# GUI front end and terminal emulator (putty, puttytel).
|
||||
GUITERM = TERMINAL window windlg winctrls sizetip winprint winutils
|
||||
+ wincfg sercfg winhelp winjump sessprep
|
||||
+ wincfg sercfg winhelp winjump sessprep winselgui
|
||||
|
||||
# Same thing on Unix.
|
||||
UXTERM = TERMINAL uxcfg sercfg uxucs uxprint timing callback miscucs
|
||||
@ -331,11 +331,11 @@ U_BE_NOSSH = be_nos_s uxser nocproxy
|
||||
putty : [G] GUITERM NONSSH WINSSH W_BE_ALL WINMISC winx11 putty.res LIBS
|
||||
puttytel : [G] GUITERM NONSSH W_BE_NOSSH WINMISC puttytel.res nogss LIBS
|
||||
plink : [C] winplink wincons NONSSH WINSSH W_BE_ALL logging WINMISC
|
||||
+ winx11 plink.res winnojmp sessprep noterm winnohlp LIBS
|
||||
+ winx11 plink.res winnojmp sessprep noterm winnohlp winselcli LIBS
|
||||
pscp : [C] pscp winsftp wincons WINSSH BE_SSH SFTP wildcard WINMISC
|
||||
+ pscp.res winnojmp winnohlp LIBS
|
||||
+ pscp.res winnojmp winnohlp winselcli LIBS
|
||||
psftp : [C] psftp winsftp wincons WINSSH BE_SSH SFTP wildcard WINMISC
|
||||
+ psftp.res winnojmp winnohlp LIBS
|
||||
+ psftp.res winnojmp winnohlp winselcli LIBS
|
||||
|
||||
pageant : [G] winpgnt pageant sshrsa sshpubk sshdes ARITH sshmd5 version
|
||||
+ tree234 MISC sshaes sshsha winsecur winpgntc aqsync sshdss sshsh256
|
||||
|
@ -871,6 +871,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
|
||||
lp_eventlog(default_logpolicy, "Running with restricted process ACL");
|
||||
}
|
||||
|
||||
winselgui_set_hwnd(hwnd);
|
||||
start_backend();
|
||||
|
||||
/*
|
||||
@ -1023,32 +1024,6 @@ void cleanup_exit(int code)
|
||||
exit(code);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up, or shut down, an AsyncSelect. Called from winnet.c.
|
||||
*/
|
||||
char *do_select(SOCKET skt, bool enable)
|
||||
{
|
||||
int msg, events;
|
||||
if (enable) {
|
||||
msg = WM_NETEVENT;
|
||||
events = (FD_CONNECT | FD_READ | FD_WRITE |
|
||||
FD_OOB | FD_CLOSE | FD_ACCEPT);
|
||||
} else {
|
||||
msg = events = 0;
|
||||
}
|
||||
if (!hwnd)
|
||||
return "do_select(): internal error (hwnd==NULL)";
|
||||
if (p_WSAAsyncSelect(skt, hwnd, msg, events) == SOCKET_ERROR) {
|
||||
switch (p_WSAGetLastError()) {
|
||||
case WSAENETDOWN:
|
||||
return "Network is down";
|
||||
default:
|
||||
return "WSAAsyncSelect(): unknown error";
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Refresh the saved-session submenu from `sesslist'.
|
||||
*/
|
||||
|
@ -38,8 +38,6 @@ StripCtrlChars *stdout_scc, *stderr_scc;
|
||||
BinarySink *stdout_bs, *stderr_bs;
|
||||
DWORD orig_console_mode;
|
||||
|
||||
WSAEVENT netevent;
|
||||
|
||||
static Backend *backend;
|
||||
Conf *conf;
|
||||
|
||||
@ -190,26 +188,6 @@ static void version(void)
|
||||
exit(0);
|
||||
}
|
||||
|
||||
char *do_select(SOCKET skt, bool enable)
|
||||
{
|
||||
int events;
|
||||
if (enable) {
|
||||
events = (FD_CONNECT | FD_READ | FD_WRITE |
|
||||
FD_OOB | FD_CLOSE | FD_ACCEPT);
|
||||
} else {
|
||||
events = 0;
|
||||
}
|
||||
if (p_WSAEventSelect(skt, netevent, events) == SOCKET_ERROR) {
|
||||
switch (p_WSAGetLastError()) {
|
||||
case WSAENETDOWN:
|
||||
return "Network is down";
|
||||
default:
|
||||
return "WSAEventSelect(): unknown error";
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t stdin_gotdata(struct handle *h, const void *data, size_t len, int err)
|
||||
{
|
||||
if (err) {
|
||||
@ -502,7 +480,7 @@ int main(int argc, char **argv)
|
||||
/*
|
||||
* Start up the connection.
|
||||
*/
|
||||
netevent = CreateEvent(NULL, false, false, NULL);
|
||||
winselcli_setup(); /* ensure event object exists */
|
||||
{
|
||||
const char *error;
|
||||
char *realhost;
|
||||
@ -558,7 +536,7 @@ int main(int argc, char **argv)
|
||||
|
||||
handles = handle_get_events(&nhandles);
|
||||
handles = sresize(handles, nhandles+1, HANDLE);
|
||||
handles[nhandles] = netevent;
|
||||
handles[nhandles] = winselcli_event;
|
||||
n = MsgWaitForMultipleObjects(nhandles+1, handles, false, ticks,
|
||||
QS_POSTMESSAGE);
|
||||
if ((unsigned)(n - WAIT_OBJECT_0) < (unsigned)nhandles) {
|
||||
|
78
windows/winselcli.c
Normal file
78
windows/winselcli.c
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Implementation of do_select() for winnet.c to use, suitable for use
|
||||
* when there's no GUI window to have network activity reported to.
|
||||
*
|
||||
* It uses WSAEventSelect, where available, to convert network
|
||||
* activity into activity on an event object, for integration into an
|
||||
* event loop that includes WaitForMultipleObjects.
|
||||
*
|
||||
* It also maintains a list of currently active sockets, which can be
|
||||
* retrieved by a front end that wants to use WinSock's synchronous
|
||||
* select() function.
|
||||
*/
|
||||
|
||||
#include "putty.h"
|
||||
|
||||
static tree234 *winselcli_sockets;
|
||||
|
||||
static int socket_cmp(void *av, void *bv)
|
||||
{
|
||||
return memcmp(av, bv, sizeof(SOCKET));
|
||||
}
|
||||
|
||||
HANDLE winselcli_event = INVALID_HANDLE_VALUE;
|
||||
|
||||
void winselcli_setup(void)
|
||||
{
|
||||
if (!winselcli_sockets)
|
||||
winselcli_sockets = newtree234(socket_cmp);
|
||||
|
||||
if (p_WSAEventSelect && winselcli_event == INVALID_HANDLE_VALUE)
|
||||
winselcli_event = CreateEvent(NULL, false, false, NULL);
|
||||
}
|
||||
|
||||
SOCKET winselcli_unique_socket(void)
|
||||
{
|
||||
if (!winselcli_sockets)
|
||||
return INVALID_SOCKET;
|
||||
|
||||
assert(count234(winselcli_sockets) <= 1);
|
||||
|
||||
SOCKET *p = index234(winselcli_sockets, 0);
|
||||
if (!p)
|
||||
return INVALID_SOCKET;
|
||||
|
||||
return *p;
|
||||
}
|
||||
|
||||
char *do_select(SOCKET skt, bool enable)
|
||||
{
|
||||
/* Check everything's been set up, for convenience of callers. */
|
||||
winselcli_setup();
|
||||
|
||||
if (enable) {
|
||||
SOCKET *ptr = snew(SOCKET);
|
||||
*ptr = skt;
|
||||
if (add234(winselcli_sockets, ptr) != ptr)
|
||||
sfree(ptr); /* already there */
|
||||
} else {
|
||||
SOCKET *ptr = del234(winselcli_sockets, &skt);
|
||||
if (ptr)
|
||||
sfree(ptr);
|
||||
}
|
||||
|
||||
if (p_WSAEventSelect) {
|
||||
int events;
|
||||
if (enable) {
|
||||
events = (FD_CONNECT | FD_READ | FD_WRITE |
|
||||
FD_OOB | FD_CLOSE | FD_ACCEPT);
|
||||
} else {
|
||||
events = 0;
|
||||
}
|
||||
|
||||
if (p_WSAEventSelect(skt, winselcli_event, events) == SOCKET_ERROR)
|
||||
return winsock_error_string(p_WSAGetLastError());
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
38
windows/winselgui.c
Normal file
38
windows/winselgui.c
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Implementation of do_select() for winnet.c to use, that uses
|
||||
* WSAAsyncSelect to convert network activity into window messages,
|
||||
* for integration into a GUI event loop.
|
||||
*/
|
||||
|
||||
#include "putty.h"
|
||||
|
||||
static HWND winsel_hwnd = NULL;
|
||||
|
||||
void winselgui_set_hwnd(HWND hwnd)
|
||||
{
|
||||
winsel_hwnd = hwnd;
|
||||
}
|
||||
|
||||
void winselgui_clear_hwnd(void)
|
||||
{
|
||||
winsel_hwnd = NULL;
|
||||
}
|
||||
|
||||
char *do_select(SOCKET skt, bool enable)
|
||||
{
|
||||
int msg, events;
|
||||
if (enable) {
|
||||
msg = WM_NETEVENT;
|
||||
events = (FD_CONNECT | FD_READ | FD_WRITE |
|
||||
FD_OOB | FD_CLOSE | FD_ACCEPT);
|
||||
} else {
|
||||
msg = events = 0;
|
||||
}
|
||||
|
||||
assert(winsel_hwnd);
|
||||
|
||||
if (p_WSAAsyncSelect(skt, winsel_hwnd, msg, events) == SOCKET_ERROR)
|
||||
return winsock_error_string(p_WSAGetLastError());
|
||||
|
||||
return NULL;
|
||||
}
|
@ -462,41 +462,6 @@ char *dir_file_cat(const char *dir, const char *file)
|
||||
* Platform-specific network handling.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Be told what socket we're supposed to be using.
|
||||
*/
|
||||
static SOCKET sftp_ssh_socket = INVALID_SOCKET;
|
||||
static HANDLE netevent = INVALID_HANDLE_VALUE;
|
||||
char *do_select(SOCKET skt, bool enable)
|
||||
{
|
||||
int events;
|
||||
if (enable)
|
||||
sftp_ssh_socket = skt;
|
||||
else
|
||||
sftp_ssh_socket = INVALID_SOCKET;
|
||||
|
||||
if (netevent == INVALID_HANDLE_VALUE)
|
||||
netevent = CreateEvent(NULL, false, false, NULL);
|
||||
|
||||
if (p_WSAEventSelect) {
|
||||
if (enable) {
|
||||
events = (FD_CONNECT | FD_READ | FD_WRITE |
|
||||
FD_OOB | FD_CLOSE | FD_ACCEPT);
|
||||
} else {
|
||||
events = 0;
|
||||
}
|
||||
if (p_WSAEventSelect(skt, netevent, events) == SOCKET_ERROR) {
|
||||
switch (p_WSAGetLastError()) {
|
||||
case WSAENETDOWN:
|
||||
return "Network is down";
|
||||
default:
|
||||
return "WSAEventSelect(): unknown error";
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int do_eventsel_loop(HANDLE other_event)
|
||||
{
|
||||
int n, nhandles, nallhandles, netindex, otherindex;
|
||||
@ -527,8 +492,8 @@ int do_eventsel_loop(HANDLE other_event)
|
||||
handles = sresize(handles, nhandles+2, HANDLE);
|
||||
nallhandles = nhandles;
|
||||
|
||||
if (netevent != INVALID_HANDLE_VALUE)
|
||||
handles[netindex = nallhandles++] = netevent;
|
||||
if (winselcli_event != INVALID_HANDLE_VALUE)
|
||||
handles[netindex = nallhandles++] = winselcli_event;
|
||||
else
|
||||
netindex = -1;
|
||||
if (other_event != INVALID_HANDLE_VALUE)
|
||||
@ -630,12 +595,13 @@ int ssh_sftp_loop_iteration(void)
|
||||
fd_set readfds;
|
||||
int ret;
|
||||
unsigned long now = GETTICKCOUNT(), then;
|
||||
SOCKET skt = winselcli_unique_socket();
|
||||
|
||||
if (sftp_ssh_socket == INVALID_SOCKET)
|
||||
if (skt == INVALID_SOCKET)
|
||||
return -1; /* doom */
|
||||
|
||||
if (socket_writable(sftp_ssh_socket))
|
||||
select_result((WPARAM) sftp_ssh_socket, (LPARAM) FD_WRITE);
|
||||
if (socket_writable(skt))
|
||||
select_result((WPARAM) skt, (LPARAM) FD_WRITE);
|
||||
|
||||
do {
|
||||
unsigned long next;
|
||||
@ -657,7 +623,7 @@ int ssh_sftp_loop_iteration(void)
|
||||
}
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(sftp_ssh_socket, &readfds);
|
||||
FD_SET(skt, &readfds);
|
||||
ret = p_select(1, &readfds, NULL, NULL, ptv);
|
||||
|
||||
if (ret < 0)
|
||||
@ -669,7 +635,7 @@ int ssh_sftp_loop_iteration(void)
|
||||
|
||||
} while (ret == 0);
|
||||
|
||||
select_result((WPARAM) sftp_ssh_socket, (LPARAM) FD_READ);
|
||||
select_result((WPARAM) skt, (LPARAM) FD_READ);
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
@ -712,7 +678,7 @@ char *ssh_sftp_get_cmdline(const char *prompt, bool no_fds_ok)
|
||||
fputs(prompt, stdout);
|
||||
fflush(stdout);
|
||||
|
||||
if ((sftp_ssh_socket == INVALID_SOCKET && no_fds_ok) ||
|
||||
if ((winselcli_unique_socket() == INVALID_SOCKET && no_fds_ok) ||
|
||||
p_WSAEventSelect == NULL) {
|
||||
return fgetline(stdin); /* very simple */
|
||||
}
|
||||
|
@ -319,6 +319,8 @@ bool socket_writable(SOCKET skt);
|
||||
void socket_reselect_all(void);
|
||||
/* Make a SockAddr which just holds a named pipe address. */
|
||||
SockAddr *sk_namedpipe_addr(const char *pipename);
|
||||
/* Turn a WinSock error code into a string. */
|
||||
const char *winsock_error_string(int error);
|
||||
|
||||
/*
|
||||
* winnet.c dynamically loads WinSock 2 or WinSock 1 depending on
|
||||
@ -347,11 +349,22 @@ DECL_WINDOWS_FUNCTION(GLOBAL, int, select,
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Provided by each client of winnet.c, and called by winnet.c to turn
|
||||
* on or off WSA*Select for a given socket.
|
||||
* Implemented differently depending on the client of winnet.c, and
|
||||
* called by winnet.c to turn on or off WSA*Select for a given socket.
|
||||
*/
|
||||
char *do_select(SOCKET skt, bool enable);
|
||||
|
||||
/*
|
||||
* Exports from winselgui.c and winselcli.c, each of which provides an
|
||||
* implementation of do_select.
|
||||
*/
|
||||
void winselgui_set_hwnd(HWND hwnd);
|
||||
void winselgui_clear_hwnd(void);
|
||||
|
||||
void winselcli_setup(void);
|
||||
SOCKET winselcli_unique_socket(void);
|
||||
extern HANDLE winselcli_event;
|
||||
|
||||
/*
|
||||
* Network-subsystem-related functions provided in other Windows modules.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user