mio, the I/O layer under Tokio, waits for sockets by opening \Device\Afd
with NtCreateFile and issuing IOCTL_AFD_POLL through NtDeviceIoControlFile,
with the completions delivered to an I/O completion port; wepoll and libuv
do the same. Every Tokio program that touches the network stopped there:
xh, Deno's fetch, Bun.
An AFD endpoint is now a handle that can join a completion port. A poll
reads AFD_POLL_INFO (the timeout, the sockets and the events wanted), waits
in the reactor on the sockets' host descriptors, and finishes as overlapped
I/O does: the output records with the events that occurred (receive,
expedited, send, disconnect, abort, local close, accept, connect failure),
the IO_STATUS_BLOCK, the event, and a packet carrying the APC context. The
native cancels end pending polls as cancelled. WSAIoctl answers
SIO_BASE_HANDLE and the SIO_BSP_HANDLE codes with the socket itself, since
no layered provider sits on it. The structures and codes are the ones those
open-source projects define; Microsoft does not document this interface.
Assisted-by: Claude Code:claude-opus-5-5
AI-Scope: the AFD endpoint, its poll and cancellation, and the base-handle codes
(cherry picked from commit 660a20304054e00ab94afef0322f9dbd0a8cbb8f)
Only the low byte of the flags argument is the caller's; the rest of the
register can hold anything, and mio's call arrived as 0x102 and was refused,
so every socket it registered failed.
Assisted-by: Claude Code:claude-opus-5-5
AI-Scope: the change
(cherry picked from commit 819372b516072d07ef0442c0fad7933874b20ad4)