3 void cli_main_loop(cliloop_pre_t pre
, cliloop_post_t post
, void *ctx
)
6 size_t skcount
= 0, sksize
= 0;
7 unsigned long now
, next
, then
;
14 const HANDLE
*extra_handles
= NULL
;
15 size_t n_extra_handles
= 0;
16 if (!pre(ctx
, &extra_handles
, &n_extra_handles
))
19 if (toplevel_callback_pending()) {
22 } else if (run_timers(now
, &next
)) {
25 if (now
- then
> next
- then
)
31 /* no need to initialise next here because we can never
35 HandleWaitList
*hwl
= get_handle_wait_list();
36 size_t winselcli_index
= -(size_t)1;
37 size_t extra_base
= hwl
->nhandles
;
38 if (winselcli_event
!= INVALID_HANDLE_VALUE
) {
39 assert(extra_base
< MAXIMUM_WAIT_OBJECTS
);
40 winselcli_index
= extra_base
++;
41 hwl
->handles
[winselcli_index
] = winselcli_event
;
43 size_t total_handles
= extra_base
+ n_extra_handles
;
44 assert(total_handles
< MAXIMUM_WAIT_OBJECTS
);
45 for (size_t i
= 0; i
< n_extra_handles
; i
++)
46 hwl
->handles
[extra_base
+ i
] = extra_handles
[i
];
48 n
= WaitForMultipleObjects(total_handles
, hwl
->handles
, false, ticks
);
50 size_t extra_handle_index
= n_extra_handles
;
52 if ((unsigned)(n
- WAIT_OBJECT_0
) < (unsigned)hwl
->nhandles
) {
53 handle_wait_activate(hwl
, n
- WAIT_OBJECT_0
);
54 } else if (winselcli_event
!= INVALID_HANDLE_VALUE
&&
55 n
== WAIT_OBJECT_0
+ winselcli_index
) {
56 WSANETWORKEVENTS things
;
61 * We must not call select_result() for any socket
62 * until we have finished enumerating within the tree.
63 * This is because select_result() may close the socket
64 * and modify the tree.
66 /* Count the active sockets. */
68 for (socket
= first_socket(&socketstate
);
69 socket
!= INVALID_SOCKET
;
70 socket
= next_socket(&socketstate
)) i
++;
72 /* Expand the buffer if necessary. */
73 sgrowarray(sklist
, sksize
, i
);
75 /* Retrieve the sockets into sklist. */
77 for (socket
= first_socket(&socketstate
);
78 socket
!= INVALID_SOCKET
;
79 socket
= next_socket(&socketstate
)) {
80 sklist
[skcount
++] = socket
;
83 /* Now we're done enumerating; go through the list. */
84 for (i
= 0; i
< skcount
; i
++) {
88 if (!p_WSAEnumNetworkEvents(socket
, NULL
, &things
)) {
89 static const struct { int bit
, mask
; } eventtypes
[] = {
90 {FD_CONNECT_BIT
, FD_CONNECT
},
91 {FD_READ_BIT
, FD_READ
},
92 {FD_CLOSE_BIT
, FD_CLOSE
},
94 {FD_WRITE_BIT
, FD_WRITE
},
95 {FD_ACCEPT_BIT
, FD_ACCEPT
},
99 noise_ultralight(NOISE_SOURCE_IOID
, socket
);
101 for (e
= 0; e
< lenof(eventtypes
); e
++)
102 if (things
.lNetworkEvents
& eventtypes
[e
].mask
) {
104 int err
= things
.iErrorCode
[eventtypes
[e
].bit
];
105 lp
= WSAMAKESELECTREPLY(eventtypes
[e
].mask
, err
);
106 select_result(wp
, lp
);
110 } else if (n
>= WAIT_OBJECT_0
+ extra_base
&&
111 n
< WAIT_OBJECT_0
+ extra_base
+ n_extra_handles
) {
112 extra_handle_index
= n
- (WAIT_OBJECT_0
+ extra_base
);
115 run_toplevel_callbacks();
117 if (n
== WAIT_TIMEOUT
) {
120 now
= GETTICKCOUNT();
123 handle_wait_list_free(hwl
);
125 if (!post(ctx
, extra_handle_index
))
132 bool cliloop_null_pre(void *vctx
, const HANDLE
**eh
, size_t *neh
)
134 bool cliloop_null_post(void *vctx
, size_t ehi
) { return true; }