1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
#include "putty.h"
void cli_main_loop(cliloop_pre_t pre, cliloop_post_t post, void *ctx)
{
SOCKET *sklist = NULL;
size_t skcount = 0, sksize = 0;
unsigned long now, next, then;
now = GETTICKCOUNT();
while (true) {
DWORD n;
DWORD ticks;
const HANDLE *extra_handles = NULL;
size_t n_extra_handles = 0;
if (!pre(ctx, &extra_handles, &n_extra_handles))
break;
if (toplevel_callback_pending()) {
ticks = 0;
next = now;
} else if (run_timers(now, &next)) {
then = now;
now = GETTICKCOUNT();
if (now - then > next - then)
ticks = 0;
else
ticks = next - now;
} else {
ticks = INFINITE;
/* no need to initialise next here because we can never
* get WAIT_TIMEOUT */
}
HandleWaitList *hwl = get_handle_wait_list();
size_t winselcli_index = -(size_t)1;
size_t extra_base = hwl->nhandles;
if (winselcli_event != INVALID_HANDLE_VALUE) {
assert(extra_base < MAXIMUM_WAIT_OBJECTS);
winselcli_index = extra_base++;
hwl->handles[winselcli_index] = winselcli_event;
}
size_t total_handles = extra_base + n_extra_handles;
assert(total_handles < MAXIMUM_WAIT_OBJECTS);
for (size_t i = 0; i < n_extra_handles; i++)
hwl->handles[extra_base + i] = extra_handles[i];
n = WaitForMultipleObjects(total_handles, hwl->handles, false, ticks);
size_t extra_handle_index = n_extra_handles;
if ((unsigned)(n - WAIT_OBJECT_0) < (unsigned)hwl->nhandles) {
handle_wait_activate(hwl, n - WAIT_OBJECT_0);
} else if (winselcli_event != INVALID_HANDLE_VALUE &&
n == WAIT_OBJECT_0 + winselcli_index) {
WSANETWORKEVENTS things;
SOCKET socket;
int i, socketstate;
/*
* We must not call select_result() for any socket
* until we have finished enumerating within the tree.
* This is because select_result() may close the socket
* and modify the tree.
*/
/* Count the active sockets. */
i = 0;
for (socket = first_socket(&socketstate);
socket != INVALID_SOCKET;
socket = next_socket(&socketstate)) i++;
/* Expand the buffer if necessary. */
sgrowarray(sklist, sksize, i);
/* Retrieve the sockets into sklist. */
skcount = 0;
for (socket = first_socket(&socketstate);
socket != INVALID_SOCKET;
socket = next_socket(&socketstate)) {
sklist[skcount++] = socket;
}
/* Now we're done enumerating; go through the list. */
for (i = 0; i < skcount; i++) {
WPARAM wp;
socket = sklist[i];
wp = (WPARAM) socket;
if (!p_WSAEnumNetworkEvents(socket, NULL, &things)) {
static const struct { int bit, mask; } eventtypes[] = {
{FD_CONNECT_BIT, FD_CONNECT},
{FD_READ_BIT, FD_READ},
{FD_CLOSE_BIT, FD_CLOSE},
{FD_OOB_BIT, FD_OOB},
{FD_WRITE_BIT, FD_WRITE},
{FD_ACCEPT_BIT, FD_ACCEPT},
};
int e;
noise_ultralight(NOISE_SOURCE_IOID, socket);
for (e = 0; e < lenof(eventtypes); e++)
if (things.lNetworkEvents & eventtypes[e].mask) {
LPARAM lp;
int err = things.iErrorCode[eventtypes[e].bit];
lp = WSAMAKESELECTREPLY(eventtypes[e].mask, err);
select_result(wp, lp);
}
}
}
} else if (n >= WAIT_OBJECT_0 + extra_base &&
n < WAIT_OBJECT_0 + extra_base + n_extra_handles) {
extra_handle_index = n - (WAIT_OBJECT_0 + extra_base);
}
run_toplevel_callbacks();
if (n == WAIT_TIMEOUT) {
now = next;
} else {
now = GETTICKCOUNT();
}
handle_wait_list_free(hwl);
if (!post(ctx, extra_handle_index))
break;
}
sfree(sklist);
}
bool cliloop_null_pre(void *vctx, const HANDLE **eh, size_t *neh)
{ return true; }
bool cliloop_null_post(void *vctx, size_t ehi) { return true; }
|