1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-07-03 04:22:47 -05: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:
Simon Tatham
2020-01-01 11:10:22 +00:00
parent ae1148267d
commit b89d17fbca
7 changed files with 147 additions and 99 deletions

78
windows/winselcli.c Normal file
View 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;
}