1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 01:48:00 +00:00
putty-source/windows/winselcli.c
Simon Tatham b89d17fbca 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'.
2020-01-04 13:52:22 +00:00

79 lines
2.0 KiB
C

/*
* 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;
}