1Windows-related issues 2====================== 3 4Supporting Windows introduces some complications due to some "fun" peculiarities 5of Windows socket API. 6 7In general, Windows does not provide a poll(2) system call. WSAPoll(2) was introduced 8in Vista and was supposed to bring this functionality, but it had a bug in it which 9Microsoft refused to fix, making it rather pointless. However, Microsoft has now 10finally fixed this bug in a build of Windows 10. So WSAPoll(2) is a viable 11method, but only on fairly new versions of Windows. 12 13Traditionally, polling has been done on windows using select(). However, this 14call works a little differently than on POSIX platforms. Whereas on POSIX 15platforms select() accepts a bitmask of FDs, on Windows select() accepts a 16structure which embeds a fixed-length array of socket handles. This is necessary 17because sockets are NT kernel handles on Windows and thus are not allocated 18contiguously like FDs. As such, Windows select() is actually very similar to 19POSIX poll(), making select() a viable option for polling on Windows. 20 21Neither select() nor poll() are, of course, high performance polling options. 22Windows does not provide anything like epoll or kqueue. For high performance 23network I/O, you are expected to use a Windows API called I/O Completion Ports 24(IOCP). 25 26Supporting these can be a pain for applications designed around polling. The reason 27is that IOCPs are a higher-level interface; it is easy to build an IOCP-like 28interface on top of polling, but it is not really possible to build a 29polling-like interface on top of IOCPs. 30 31For this reason it's actually common for asynchronous I/O libraries to basically 32contain two separate implementations of their APIs internally, or at least a 33substantial chunk of their code (e.g. libuv, nanomsg). It turns out to be easier 34just to write a poll-based implementation of an I/O reactor and an IOCP-based 35implementation than try to overcome the impedance discontinuities. 36 37The difference between polling and IOCPs is that polling reports *readiness* 38whereas IOCPs report *completion of an operation*. For example, in the IOCP 39model, you make a read or write on a socket and an event is posted to the IOCP 40when the read or write is complete. This is a fundamentally different model and 41actually more similar to a high-level asynchronous I/O library such as libuv or 42so on. 43 44Evaluation of the existing demos and their applicability to Windows IOCP: 45 46- ddd-01-conn-blocking: Blocking example, use of IOCP is not applicable. 47 48- ddd-02-conn-nonblocking: Socket is managed by OpenSSL, and IOCP is not 49 supported. 50 51- ddd-03-fd-blocking: Blocking example, use of IOCP is not applicable. 52 53- ddd-04-fd-nonblocking: libssl is passed an FD with BIO_set_fd. 54 55 BIO_s_sock doesn't appear to support overlapped (that is, IOCP-based) I/O 56 as this requires use of special WSASend() and WSARecv() functions, rather 57 than standard send()/recv(). 58 59 Since libssl already doesn't support IOCP for use of BIO_s_sock, 60 we might say here that any existing application using BIO_s_sock 61 obviously isn't trying to use IOCP, and therefore we don't need to 62 worry about the adapability of this example to IOCP. 63 64- ddd-05-mem-nonblocking: Since the application is in full control of passing 65 data from the memory BIO to the network, or vice versa, the application 66 can use IOCP if it wishes. 67 68 This is demonstrated in the following demo: 69 70- ddd-06-mem-uv: This demo uses a memory BIO and libuv. Since libuv supports 71 IOCP, it proves that a memory BIO can be used to support IOCP-based usage. 72 73Further, a cursory examination of code on GitHub seems to suggest that when 74people do use IOCP with libssl, they do it using memory BIOs passed to libssl. 75So ddd-05 and ddd-06 essentially demonstrate this use case, especially ddd-06 as 76it uses IOCP internally on Windows. 77 78My conclusion here is that since libssl does not support IOCP in the first 79place, we don't need to be particularly worried about this. But in the worst 80case there are always workable solutions, as in demos 5 and 6. 81